home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2004 #11
/
Amiga Plus CD - 2004 - No. 11.iso
/
AmiSoft
/
Game
/
misc
/
WormWars.lha
/
WormWars
/
Source
/
system.c
< prev
next >
Wrap
C/C++ Source or Header
|
2004-08-22
|
120KB
|
3,229 lines
// 1. INCLUDES -----------------------------------------------------------
#include <proto/asl.h>
#include <proto/exec.h>
#include <proto/diskfont.h>
#include <proto/dos.h>
#include <proto/gadtools.h>
#include <proto/graphics.h>
#include <proto/icon.h>
#include <proto/intuition.h>
#include <proto/lowlevel.h>
#include <proto/timer.h>
#include <clib/alib_protos.h>
#ifdef __STORM__
#include <proto/utility.h>
#endif
#ifdef LATTICE
#include <clib/utility_protos.h>
#endif
#include <devices/audio.h>
#include <devices/gameport.h>
#include <exec/alerts.h>
#include <exec/execbase.h>
#include <graphics/gfxbase.h>
#include <hardware/cia.h>
#include "diff.h"
#include "same.h"
#include "amiga.h"
#include "libproto.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
// 2. DEFINES ------------------------------------------------------------
typedef LONG Fixed; /* A fixed-point value, 16 bits to the left
of the point and 16 to the right. A Fixed
is a number of 2**16ths, ie. 65536ths. */
typedef struct
{ ULONG oneShotHiSamples, /* # samples in the high octave 1-shot part */
repeatHiSamples, /* # samples in the high octave repeat part */
samplesPerHiCycle; /* # samples/cycle in high octave, else 0 */
UWORD samplesPerSec; /* data sampling rate */
UBYTE ctOctave, /* # of octaves of waveforms */
sCompression; /* data compression technique used */
Fixed volume; /* playback nominal volume from 0 to Unity
(full volume). Map this value into the
output hardware's dynamic range (0-64). */
} Voice8Header;
#define PATIENCE 50 // in INTUITICKs
#define CONFIGLENGTH 23
#define ONE_BILLION 1000000000
/* joysticks */
#define JOYUP 1
#define JOYDOWN 2
#define JOYLEFT 4
#define JOYRIGHT 8
#define JOYFIRE1 16
#define JOYFIRE2 32
#define POTGOR *(UWORD *)0xDFF016
#define OLD 1
#define NEW 0
/* Help|About... window */
#define ABOUTLINES 6
#define ABOUTSHADOW DARKGREY
#define ABOUTSHINE LIGHTGREY
#define PROJECTX 128
#define PROJECTY 75
#define KICKSTARTX 104
#define KICKSTARTY 91
#define WORKBENCHX 104
#define WORKBENCHY 99
/* fxable/musicable */
#define FAILED 0 // tried and failed
#define SUCCEEDED 1 // tried and succeeded
#define UNTRIED 2 // untried, will try at startup
#define DEFER 3 // untried, will try when needed
/* miscellaneous */
#define ANIMDELAY 1800
#define ENTIREXPIXEL 640
#define ENTIREYPIXEL 512
#define MAXXSIZE 1280
#define MAXYSIZE 1024
#define FIELDCENTREXPIXEL (STARTXPIXEL + ((ENDXPIXEL - STARTXPIXEL) / 2))
#define FIELDCENTREYPIXEL (STARTYPIXEL + ((ENDYPIXEL - STARTYPIXEL) / 2))
/* constant strings used more than once */
#define PATTERN "(#?.lset)"
#define OLDKICKSTART "Worm Wars: You need Kickstart R2.04+!\n(Can't open intuition.library V37+!)\n"
#define ID_8SVX MAKE_ID('8','S','V','X')
#define ID_BODY MAKE_ID('B','O','D','Y')
#define ID_VHDR MAKE_ID('V','H','D','R')
#define PALCLOCK 3546895
#define NTSCCLOCK 3579545
#define SOFT 32
#define LOUD 64 /* = Unity */
#define RUNDOWNX (FIELDCENTREXPIXEL - 152)
#define RUNDOWNX_1ST 32
#define RUNDOWNX_2ND (32 + (FONTX * 14))
#define RUNDOWNX_3RD (32 + (FONTX * 21))
#define RUNDOWNX_4TH (32 + (FONTX * 28))
#define RUNDOWNY (FIELDCENTREYPIXEL - 32)
#define RUNDOWNY_2ND 12
#define RUNSTRINGLENGTH 27
#define INDEX_ANIMATIONS 21
#define INDEX_CREATEICONS 22
#define INDEX_ENGRAVEDSQUARES 23
#define INDEX_SHOWTITLEBAR 24
// 3. EXPORTED VARIABLES -------------------------------------------------
EXPORT struct Window *HelpWindowPtr = NULL,
*MainWindowPtr = NULL;
EXPORT ULONG DisplayWidth = ENTIREXPIXEL,
DisplayHeight = ENTIREYPIXEL;
EXPORT struct Menu* MenuPtr = NULL;
EXPORT struct VisualInfo* VisualInfoPtr = NULL;
EXPORT struct timerequest* TimerRqPtr = NULL;
EXPORT struct Screen* ScreenPtr = NULL;
EXPORT ABOOL icons = TRUE,
titlebar = TRUE;
EXPORT struct Library* LowLevelBase = NULL;
EXPORT struct Device* TimerBase = NULL;
EXPORT struct UtilityBase* UtilityBase = NULL;
// 4. IMPORTED VARIABLES -------------------------------------------------
IMPORT struct ExecBase* SysBase;
IMPORT ABOOL anims,
engraved,
modified,
randomflag,
turbo;
IMPORT TEXT pathname[81],
date[DATELENGTH + 1],
times[TIMELENGTH + 1],
stattext[7 + 1];
IMPORT UBYTE board[MAXLEVELS + 1][MINFIELDX + 1][MINFIELDY + 1],
field[MAXFIELDX + 1][MAXFIELDY + 1],
missileframes[4][MISSILEFRAMES + 1],
birdframes[BIRDFRAMES + 1];
IMPORT SBYTE a, level, levels, players, sourcelevel,
startx[MAXLEVELS + 1], starty[MAXLEVELS + 1];
IMPORT UWORD ImageData[ARRAYSIZE + 1][SQUAREY * DEPTH4];
IMPORT SWORD secondsleft, secondsperlevel,
fieldx, fieldy;
IMPORT ULONG delay, r,
quantity[5][3];
IMPORT struct HiScoreStruct hiscore[HISCORES + 1];
IMPORT struct WormStruct worm[4];
IMPORT struct CreatureInfoStruct creatureinfo[SPECIES + 1];
IMPORT struct Image Image;
// 5. MODULE VARIABLES ---------------------------------------------------
MODULE ABOOL clockdrawn = FALSE,
eversent[4],
evertimed = FALSE,
first = TRUE,
ignore = FALSE,
quiet = FALSE,
saveconfig = FALSE;
MODULE SBYTE AudioClosed = TRUE,
OldPri = 0,
TimerClosed = TRUE;
MODULE UBYTE fxable = UNTRIED,
mode = NULL,
musicable = UNTRIED;
MODULE ULONG fsize,
millielapsed,
receipter[4] = {(ULONG) -1, (ULONG) -1, (ULONG) -1, (ULONG) -1};
MODULE UBYTE* fbase = NULL;
MODULE BPTR FilePtr = NULL;
MODULE APTR OldWindowPtr = NULL;
MODULE SBYTE hiframe = -1;
MODULE UBYTE ConfigBuffer[CONFIGLENGTH],
song = 0;
MODULE UWORD DisplayDepth = DEPTH5;
MODULE ULONG DisplayID = HIRES_KEY | PAL_MONITOR_ID | LACE;
MODULE struct Gadget *CycleGadgetPtr[4] = {NULL, NULL, NULL, NULL},
*GListPtr = NULL,
*PrevGadgetPtr = NULL,
*ShuffleGadgetPtr = NULL,
*StringGadgetPtr[5] = {NULL, NULL, NULL, NULL, NULL};
MODULE struct MsgPort *AudioPortPtr[4] = {NULL, NULL, NULL, NULL},
*TimerPortPtr = NULL;
MODULE struct timeval *TimeValPtr = NULL;
MODULE struct CIA* CIAPtr = (struct CIA *) 0xBFE001;
MODULE struct RDArgs* ArgsPtr = NULL;
MODULE struct FileRequester* ASLRqPtr = NULL;
MODULE struct IOAudio* AudioRqPtr[4] = {NULL, NULL, NULL, NULL};
MODULE struct TextFont* FontPtr = NULL;
MODULE struct Process* ProcessPtr = NULL;
MODULE struct MMD0* SongPtr[7] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
MODULE struct WBArg* WBArg = NULL;
MODULE struct WBStartup* WBMsg = NULL;
MODULE struct Library *ASLBase = NULL,
*DiskFontBase = NULL,
*MEDPlayerBase = NULL;
// 6. MODULE STRUCTURES --------------------------------------------------
MODULE struct NewGadget StringGadget =
{ 0, 0,
179, 12,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
}, ShuffleGadget =
{ 0, 0,
0, 0,
NULL,
NULL,
NULL,
NULL,
NULL
}, CycleGadget =
{ 0, 0,
128, 13,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL
};
MODULE struct
{ STRPTR filename;
BYTE volume;
ULONG length[2], size, speed, bank;
UBYTE* base;
} samp[SAMPLES + 1] =
{ { "PROGDIR:fx/dog.8svx", SOFT}, /* FXBORN_DOG */
{ "PROGDIR:fx/rain.8svx", SOFT}, /* FXBORN_RAIN */
{"PROGDIR:fx/lightning.8svx", LOUD}, /* FXGET_LIGHTNING */
{ "PROGDIR:fx/missile.8svx", LOUD}, /* FXBORN_MISSILE */
{ "PROGDIR:fx/protect.8svx", SOFT}, /* FXBORN_PROTECTOR */
{ "PROGDIR:fx/death.8svx", LOUD}, /* FXDEATH_WORM */
{ "PROGDIR:fx/enclose.8svx", LOUD}, /* FXDO_ENCLOSE */
{ "PROGDIR:fx/fragment.8svx", SOFT}, /* FXBORN_FRAGMENT */
{ "PROGDIR:fx/ammo.8svx", LOUD}, /* FXGET_AMMO */
{ "PROGDIR:fx/cyclone.8svx", LOUD}, /* FXGET_CYCLONE */
{ "PROGDIR:fx/fx.8svx", SOFT}, /* FXGET_RAIN */
{ "PROGDIR:fx/grower.8svx", SOFT}, /* FXGET_GROWER */
{ "PROGDIR:fx/object.8svx", SOFT}, /* FXGET_OBJECT */
{ "PROGDIR:fx/powerup.8svx", LOUD}, /* FXGET_POWERUP */
{ "PROGDIR:fx/grave.8svx", SOFT}, /* FXGET_GRAVE */
{ "PROGDIR:fx/amigan.8svx", SOFT}, /* FXHELP */
{ "PROGDIR:fx/shoot.8svx", SOFT}, /* FXUSE_AMMO */
{ "PROGDIR:fx/armour.8svx", SOFT}, /* FXUSE_ARMOUR */
{ "PROGDIR:fx/bomb.8svx", LOUD}, /* FXUSE_BOMB */
{ "PROGDIR:fx/teleport.8svx", SOFT}, /* FXUSE_TELEPORT */
{ "PROGDIR:fx/bird.8svx", SOFT}, /* FXBORN_BIRD */
{ "PROGDIR:fx/green.8svx", SOFT}, /* FXPAIN */
{ "PROGDIR:fx/red.8svx", SOFT},
{ "PROGDIR:fx/blue.8svx", SOFT},
{ "PROGDIR:fx/yellow.8svx", SOFT},
{ "PROGDIR:fx/applause.8svx", SOFT}, /* FXAPPLAUSE (after each new hiscore) */
{ "PROGDIR:fx/gameover.8svx", LOUD}, /* FXGAMEOVER (if all worms are dead) */
{ "PROGDIR:fx/click.8svx", SOFT}, /* FXCLICK (rundown, keypresses) */
{ "PROGDIR:fx/riff.8svx", LOUD}, /* FXRIFF (after each rundown) */
{ "PROGDIR:fx/siren.8svx", SOFT}, /* FXSIREN (out of time) */
{ "PROGDIR:fx/ding.8svx", SOFT} /* FXDING */
};
MODULE struct NewMenu NewMenu[] =
{ { NM_TITLE, "Project", 0 , 0, 0, 0}, // 0
{ NM_ITEM, "New", "N", 0, 0, 0}, // 1
{ NM_ITEM, "Open...", "O", 0, 0, 0}, // 2
{ NM_ITEM, "Revert", "R", 0, 0, 0}, // 3
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 4
{ NM_ITEM, "Save", "S", 0, 0, 0}, // 5
{ NM_ITEM, "Save As...", "A", 0, 0, 0}, // 6
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 7
{ NM_ITEM, "Delete...", "D", 0, 0, 0}, // 8
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 9
{ NM_ITEM, "Quit", "Q", 0, 0, 0}, // 10
{ NM_TITLE, "Edit", 0 , NM_MENUDISABLED, 0, 0}, // 11
{ NM_ITEM, "Cut", "X", 0, 0, 0}, // 12
{ NM_ITEM, "Copy", "C", 0, 0, 0}, // 13
{ NM_ITEM, "Paste", "V", 0, 0, 0}, // 14
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 15
{ NM_ITEM, "Erase", "E", 0, 0, 0}, // 16
{ NM_ITEM, "Delete", 0 , 0, 0, 0}, // 17
{ NM_ITEM, "Insert", 0 , 0, 0, 0}, // 18
{ NM_ITEM, "Append", 0 , 0, 0, 0}, // 19
{ NM_TITLE, "Settings", 0 , 0, 0, 0}, // 20
{ NM_ITEM, "Animations?", "T", CHECKIT | MENUTOGGLE, 0, 0}, // 21
{ NM_ITEM, "Create Icons?", "I", CHECKIT | MENUTOGGLE, 0, 0}, // 22
{ NM_ITEM, "Engraved Squares?", 0 , CHECKIT | MENUTOGGLE, 0, 0}, // 23
{ NM_ITEM, "Show Titlebar?", "B", CHECKIT | MENUTOGGLE, 0, 0}, // 24
{ NM_TITLE, "Help", 0 , 0, 0, 0}, // 25
{ NM_ITEM, "Creatures...", "1", 0, 0, 0}, // 26
{ NM_ITEM, "Objects...", "2", 0, 0, 0}, // 27
{ NM_ITEM, NM_BARLABEL, 0 , 0, 0, 0}, // 28
{ NM_ITEM, "About...", "?", 0, 0, 0}, // 29
{ NM_END, NULL, 0 , 0, 0, 0} // 30
};
MODULE STRPTR CycleOptions[4][6] =
{ { "None",
"Amiga",
"Joystick 3",
"Gamepad 3",
"Lt. Kybd",
NULL
},
{ "None",
"Amiga",
"Joystick 4",
"Gamepad 4",
"Rt. Kybd",
NULL
},
{ "None",
"Amiga",
"Joystick 2",
"Gamepad 2",
NULL,
NULL
},
{ "None",
"Amiga",
"Joystick 1",
"Gamepad 1",
NULL,
NULL
} },
sfxerror[] =
{ "No errors.",
"Can't open file!",
"Can't read file!",
"Not an IFF 8SVX; too short!",
"Not an IFF FORM!",
"No memory for read!",
"Read error!",
"Malformed IFF; too short!",
"Not an IFF 8SVX!",
"No chip memory!"
},
objectdesc[LASTOBJECT + 1] =
{ "AFFIXER: Stops protectors rotating.",
"AMMO: 5 bullets.",
"ARMOUR: Immune to most damage.",
"AUTOJUMP: Automagically jump. :-)",
"BONUS: Awards the next number.",
"BRAKES: Enables very slow speed.",
"CONVERTER: Fragments to missiles.",
"CUTTER: Cuts a tunnel through tail.",
"CYCLONE: Unleashes a cyclone.",
"ENCLOSER: Rectangular enclosure.",
"GLOW: Leaves a glowing tail.",
"GROWER: Enlarges silver and gold.",
"ICE: Freezes enemies.",
"LIGHTNING: Flashes around tail.",
"MAGNET: Attracts objects.",
"MINI BOMB: A minor explosion.",
"MINI HEALER: 5 lives.",
"MISSILE: A guided missile.",
"MULTIPLIER: More points.",
"POWER: Thicker bullets.",
"PROTECTOR: An orbiting companion.",
"PULSE: Fragment explosion.",
"PUSHER: Lets you push things.",
"REMNANTS: Bullets leave a trail.",
"SIDESHOT: Shoot sideways.",
"SLAYER: Smart bomb.",
"SLOWER: Slows creatures down.",
"SUPER BOMB: A major explosion.",
"SUPER HEALER: 20 lives.",
"SWITCHER: Changes tail colours.",
"TREASURE: Treasure level.",
"UMBRELLA: Skips 2-3 levels."
};
MODULE struct
{ WORD x, y;
STRPTR text;
} about[ABOUTLINES + 1] =
{ {72, 27, ABOUTSTRING },
{72, 35, RELEASEDATE },
{72, 51, COPYRIGHT },
{72, 59, "By James R. Jacobs" },
{16, 75, "Fieldset size: bytes" },
{16, 91, "Kickstart:" },
{16, 99, "Workbench:" }
};
MODULE struct
{ UBYTE scancode;
BYTE player, deltax, deltay, special;
BOOL down;
} key[NUMKEYS + 1] =
{ {Q, 0, -1, -1, MOVE, FALSE},
{W, 0, 0, -1, MOVE, FALSE},
{KEY_E, 0, 1, -1, MOVE, FALSE},
{A, 0, -1, 0, MOVE, FALSE},
{S, 0, 0, 1, MOVE, FALSE},
{D, 0, 1, 0, MOVE, FALSE},
{Z, 0, -1, 1, MOVE, FALSE},
{KEY_X, 0, 1, 1, MOVE, FALSE},
{C, 0, 1, 1, MOVE, FALSE},
{NUMERICSEVEN, 1, -1, -1, MOVE, FALSE},
{NUMERICEIGHT, 1, 0, -1, MOVE, FALSE},
{NUMERICNINE, 1, 1, -1, MOVE, FALSE},
{NUMERICFOUR, 1, -1, 0, MOVE, FALSE},
{NUMERICFIVE, 1, 0, 1, MOVE, FALSE},
{NUMERICSIX, 1, 1, 0, MOVE, FALSE},
{NUMERICONE, 1, -1, 1, MOVE, FALSE},
{NUMERICTWO, 1, 0, 1, MOVE, FALSE},
{NUMERICTHREE, 1, 1, 1, MOVE, FALSE},
{UP, 1, 0, -1, ONEHUMAN, FALSE},
{DOWN, 1, 0, 1, ONEHUMAN, FALSE},
{RIGHT, 1, 1, 0, ONEHUMAN, FALSE},
{LEFT, 1, -1, 0, ONEHUMAN, FALSE},
{SPACEBAR, 0, 0, 0, AMMO, FALSE},
{NUMERICZERO, 1, 0, 0, AMMO, FALSE},
{ENTER, 1, 0, 0, AMMO, FALSE},
{HELP, 0, 0, 0, TRAINER, FALSE},
{NUMERICSLASH, 0, 0, 0, TRAINER, FALSE},
{NUMERICASTERISK, 0, 0, 0, TRAINER, FALSE},
{NUMERICPLUS, 0, 0, 0, TRAINER, FALSE},
{NUMERICMINUS, 0, 0, 0, TRAINER, FALSE}
}; /* Never leave unused keys in this structure. */
#define CREATUREHELPS 27
MODULE struct
{ UBYTE image;
STRPTR desc;
} creaturehelp[CREATUREHELPS + 1] =
{ {ANT, "Ant" },
{BEAR, "Bear" },
{BIRD, "Bird" },
{BULL, "Bull" },
{CAMEL, "Camel" },
{CLOUD, "Cloud" },
{CYCLONE_C, "Cyclone" },
{DOG, "Dog" },
{ELEPHANT, "Elephant" },
{FISH, "Fish" },
{FROG, "Frog" },
{GIRAFFE, "Giraffe" },
{GOOSE, "Goose" },
{HORSE, "Horse" },
{KANGAROO, "Kangaroo" },
{MONKEY, "Monkey" },
{MOUSE, "Mouse" },
{ORB, "Orb" },
{OCTOPUS, "Octopus" },
{OTTER, "Otter" },
{LASTPROTECTOR, "Protector" },
{RABBIT, "Rabbit" },
{RAIN, "Rain" },
{SALAMANDER, "Salamander"},
{SLIME, "Slime" },
{SNAIL, "Snail" },
{SPIDER, "Spider" },
{LASTHEAD, "Worm" }
};
MODULE struct Chunk
{ LONG ckID;
LONG ckSize;
LONG ckType;
void* ckData;
struct Chunk* ckNext;
};
MODULE struct EasyStruct EasyStruct =
{ sizeof(struct EasyStruct),
0,
TITLEBAR,
"Fieldset/highscores have been modified.",
"Continue|Cancel"
};
// 7. MODULE FUNCTIONS ---------------------------------------------------
MODULE ABOOL beginfx(void);
MODULE ABOOL firebutton(void);
MODULE void freefx(void);
MODULE void loadthefx(void);
MODULE void loadthemusic(void);
MODULE void matchtool(SBYTE player, char* s);
MODULE void parsewb(void);
MODULE UBYTE ReadJoystick(UWORD joynum);
MODULE ABOOL beginfx(void)
{ AUTO SBYTE i;
PERSIST UBYTE chan[] = {15};
for (i = 0; i <= 3; i++)
{ eversent[i] = FALSE;
if (!(AudioPortPtr[i] = (struct MsgPort *) CreateMsgPort()))
{ freefx();
draw(MUSICICON, ICONY, BLACKENED);
mode = FALSE;
say("No port for effects!", RED);
anykey(TRUE);
return FALSE;
} else if (!(AudioRqPtr[i] = (struct IOAudio *) CreateIORequest(AudioPortPtr[i], sizeof(struct IOAudio))))
{ freefx();
draw(MUSICICON, ICONY, BLACKENED);
mode = FALSE;
say("No I/O memory for effects!", RED);
anykey(TRUE);
return FALSE;
} }
AudioRqPtr[0]->ioa_Request.io_Message.mn_ReplyPort = AudioPortPtr[0];
AudioRqPtr[0]->ioa_Request.io_Message.mn_Node.ln_Pri = 127;
AudioRqPtr[0]->ioa_AllocKey = 0;
AudioRqPtr[0]->ioa_Data = chan;
AudioRqPtr[0]->ioa_Length = 1;
if (AudioClosed = OpenDevice(AUDIONAME, 0L, (struct IORequest *) AudioRqPtr[0], 0L))
{ freefx();
draw(MUSICICON, ICONY, BLACKENED);
mode = FALSE;
say("Can't allocate all channels for effects!", RED);
anykey(TRUE);
return FALSE;
} else
{ for (i = 1; i <= 3; i++)
CopyMem(AudioRqPtr[0], AudioRqPtr[i], sizeof(struct IOAudio));
return TRUE;
} }
MODULE ABOOL firebutton(void)
{ UBYTE PortState = ReadJoystick(1);
if (PortState & JOYFIRE1) // don't check JOYFIRE2
{ return(TRUE);
} else return(FALSE);
}
MODULE void freefx(void)
{ SBYTE i;
stopfx();
if (!AudioClosed)
{ CloseDevice((struct IORequest *) AudioRqPtr[0]);
AudioClosed = TRUE;
}
for (i = 0; i <= 3; i++)
{ if (AudioRqPtr[i])
{ DeleteIORequest(AudioRqPtr[i]);
AudioRqPtr[i] = NULL;
}
if (AudioPortPtr[i])
{ DeleteMsgPort(AudioPortPtr[i]);
AudioPortPtr[i] = NULL;
} }
if (fbase)
{ FreeMem(fbase, fsize);
fbase = NULL;
}
if (FilePtr)
{ Close(FilePtr);
FilePtr = NULL;
} }
MODULE void loadthefx(void)
{ UBYTE* p8data;
TEXT saystring[SAYLIMIT + 1];
SBYTE code = 0, i,
iobuffer[8]; /* buffer for 8SVX.VHDR */
SBYTE* psample[2]; /* sample pointers */
struct Chunk* p8Chunk; /* pointers for 8SVX parsing */
Voice8Header* pVoice8Header = NULL; // only set to NULL to avoid spurious warnings
ULONG rd8count;
say("Loading sound effects...", WHITE);
fxable = SUCCEEDED;
for (i = 0; i <= SAMPLES; i++)
samp[i].base = NULL;
for (i = 0; i <= SAMPLES; i++)
{ if (!(FilePtr = Open(samp[i].filename, MODE_OLDFILE)))
code = 1; /* can't open file */
else
{ rd8count = Read(FilePtr, iobuffer, 8L);
if (rd8count == -1)
code = 2; /* can't read file */
elif (rd8count < 8)
code = 3; /* not an IFF 8SVX; too short */
else
{ p8Chunk = (struct Chunk *) iobuffer;
if (p8Chunk->ckID != ID_FORM)
code = 4; /* not an IFF FORM */
elif (!(fbase = (UBYTE *) AllocMem(fsize = p8Chunk->ckSize, MEMF_PUBLIC | MEMF_CLEAR)))
code = 5; /* no memory for read */
else
{ p8data = fbase;
rd8count = Read(FilePtr, p8data, p8Chunk->ckSize);
if (rd8count == -1)
code = 6; /* read error */
elif (rd8count < p8Chunk->ckSize)
code = 7; /* malformed IFF; too short */
elif (MAKE_ID(*p8data, *(p8data + 1), *(p8data + 2), *(p8data + 3)) != ID_8SVX)
code = 8; /* not an IFF 8SVX */
else
{ p8data = p8data + 4;
while (p8data < fbase + fsize)
{ p8Chunk = (struct Chunk *) p8data;
switch(p8Chunk->ckID)
{
case ID_VHDR:
pVoice8Header = (Voice8Header *) (p8data + 8L);
break;
case ID_BODY:
psample[0] = (SBYTE *) (p8data + 8L);
psample[1] = psample[0] + pVoice8Header->oneShotHiSamples;
samp[i].length[0] = (ULONG) pVoice8Header->oneShotHiSamples;
samp[i].length[1] = (ULONG) pVoice8Header->repeatHiSamples;
/* To grab the volume level from the IFF
8SVX file itself, add this line here:
samp[i].volume = (SBYTE) (pVoice8Header->volume / 156); */
break;
default:
break;
}
p8data += 8L + p8Chunk->ckSize;
if (p8Chunk->ckSize & 1L == 1)
p8data++;
}
if (samp[i].length[0] == 0)
samp[i].bank = 1;
else samp[i].bank = 0;
if (samp[i].length[samp[i].bank] <= 102400)
samp[i].size = samp[i].length[samp[i].bank];
else samp[i].size = 102400;
samp[i].base = (UBYTE *) AllocMem(samp[i].size, MEMF_CHIP | MEMF_CLEAR);
if (!samp[i].base)
code = 9; /* no chip memory */
else
{ CopyMem(psample[samp[i].bank], samp[i].base, samp[i].size);
psample[samp[i].bank] += samp[i].size;
if (GfxBase->DisplayFlags & PAL) // PAL clock
{ samp[i].speed = PALCLOCK / pVoice8Header->samplesPerSec;
} else // NTSC clock
{ samp[i].speed = NTSCCLOCK / pVoice8Header->samplesPerSec;
}
/* "The maximum frequency achievable depends on the screen rate because
the Paula audio DMA period depends on the horizontal refresh rate, but the
actual clock rate of Paula by which the audio DA converters are driven
depends really only on the clock rate.
It's fixed for either PAL or NTSC machines, NOT for PAL or NTSC screen
modes. Hence just the two values that are given in the RKRMs are
completely sufficient. Note that running an NTSC screen on a PAL machine
does not change the system clock and hence neither the audio frequency.
It changes horizontal timing and vertical timing, and hence the minimal
audio period." - Thomas `Thor' Richter. */
if (fbase)
{ FreeMem(fbase, fsize);
fbase = NULL;
}
if (FilePtr)
{ Close(FilePtr);
FilePtr = NULL;
} } } } } }
if (code)
{ freefx();
fxable = FAILED;
strcpy(saystring, samp[i].filename);
strcat(saystring, ": ");
strcat(saystring, sfxerror[code]);
say(saystring, RED);
anykey(TRUE);
break;
} } }
MODULE void loadthemusic(void)
{ if (!(MEDPlayerBase = OpenLibrary("medplayer.library", 0L)))
{ say("Can't open MEDPlayer.library!", RED);
anykey(TRUE);
} else
{ say("Loading music...", WHITE);
if
( (SongPtr[0] = (struct MMD0 *) LoadModule("PROGDIR:music/title.MED"))
&& (SongPtr[1] = (struct MMD0 *) LoadModule("PROGDIR:music/over.MED"))
&& (SongPtr[2] = (struct MMD0 *) LoadModule("PROGDIR:music/editor.MED"))
&& (SongPtr[3] = (struct MMD0 *) LoadModule("PROGDIR:music/bonus.MED"))
&& (SongPtr[4] = (struct MMD0 *) LoadModule("PROGDIR:music/game1.MED"))
&& (SongPtr[5] = (struct MMD0 *) LoadModule("PROGDIR:music/game2.MED"))
&& (SongPtr[6] = (struct MMD0 *) LoadModule("PROGDIR:music/game3.MED"))
)
{ musicable = SUCCEEDED;
} else
{ say("Can't load music!", RED);
anykey(TRUE);
} } }
MODULE void matchtool(SBYTE player, char* s)
{ if (player <= 1 && (MatchToolValue(s, "KYBD") || MatchToolValue(s, "KEYBOARD")))
{ worm[player].control = KEYBOARD;
} elif (MatchToolValue(s, "JOY") || MatchToolValue(s, "STICK") || MatchToolValue(s, "JOYSTICK"))
{ worm[player].control = JOYSTICK;
} elif (MatchToolValue(s, "GAMEPAD") || MatchToolValue(s, "PAD"))
{ if (!LowLevelBase)
{ Printf("Worm Wars: Can't open lowlevel.library!\n");
cleanexit(EXIT_FAILURE);
}
worm[player].control = GAMEPAD;
} elif (MatchToolValue(s, "AMIGA"))
{ worm[player].control = AMIGA;
} elif (MatchToolValue(s, "NONE"))
{ worm[player].control = NONE;
} }
MODULE void parsewb(void)
{ struct DiskObject* DiskObject;
STRPTR* ToolArray;
STRPTR s;
if ((*WBArg->wa_Name) && (DiskObject = GetDiskObject(WBArg->wa_Name)))
{ ToolArray = (STRPTR *) DiskObject->do_ToolTypes;
if (s = FindToolType(ToolArray, "NOPRELOAD"))
{ fxable = musicable = DEFER;
}
if (s = FindToolType(ToolArray, "NOANIMS" ))
{ anims = FALSE;
}
if (s = FindToolType(ToolArray, "NOICONS" ))
{ icons = FALSE;
}
if (s = FindToolType(ToolArray, "SHUFFLE" ))
{ randomflag = TRUE;
}
if (s = FindToolType(ToolArray, "QUIET" ))
{ quiet = TRUE;
}
if (s = FindToolType(ToolArray, "FILE" ))
{ strcpy(pathname, WBArg->wa_Name);
}
if (s = FindToolType(ToolArray, "GREEN" ))
{ matchtool(0, s);
}
if (s = FindToolType(ToolArray, "RED" ))
{ matchtool(1, s);
}
if (s = FindToolType(ToolArray, "BLUE" ))
{ matchtool(2, s);
}
if (s = FindToolType(ToolArray, "YELLOW" ))
{ matchtool(3, s);
}
FreeDiskObject(DiskObject);
} }
MODULE UBYTE ReadJoystick(UWORD joynum)
{
#ifdef LATTICE
extern struct Custom far custom;
#endif
#ifdef __STORM__
extern struct Custom custom;
#endif
UBYTE ret = 0;
UWORD joy;
if (joynum == 0)
joy = custom.joy0dat;
else joy = custom.joy1dat;
ret += (joy >> 1 ^ joy) & 0x0100 ? JOYUP : 0;
ret += (joy >> 1 ^ joy) & 0x0001 ? JOYDOWN : 0;
ret += joy & 0x0200 ? JOYLEFT : 0;
ret += joy & 0x0002 ? JOYRIGHT : 0;
if (joynum == 0)
{ ret += !(CIAPtr->ciapra & 0x0040) ? JOYFIRE1 : 0; /* read firebuttons */
ret += !(POTGOR & 0x0400) ? JOYFIRE2 : 0; /* on joyport 0 */
} else
{ ret += !(CIAPtr->ciapra & 0x0080) ? JOYFIRE1 : 0; /* read firebuttons */
ret += !(POTGOR & 0x0400) ? JOYFIRE2 : 0; /* on joyport 1 */
}
return(ret);
}
// 8. EXPORTED FUNCTIONS -------------------------------------------------
EXPORT int main(int argc, char** argv)
{
BPTR FileHandle,
OldDir;
SBYTE player,
which;
TEXT saystring[SAYLIMIT + 1];
SWORD oldsecondsleft = -1;
ULONG fonttag,
publictag;
SLONG i,
args[11] = {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
struct ScreenModeRequester* smr;
ULONG elapsed;
ABOOL ok;
UWORD Pens[13] =
{ BLACK, /* DETAILPEN text in title bar */
WHITE, /* BLOCKPEN fill title bar */
BLACK, /* TEXTPEN regular text on BACKGROUNDPEN */
WHITE, /* SHINEPEN bright edge */
MEDIUMGREY,/* SHADOWPEN dark edge */
BLUE, /* FILLPEN filling active window borders
and selected gadgets */
BLACK, /* FILLTEXTPEN text rendered over FILLPEN */
LIGHTGREY, /* BACKGROUNDPEN background colour */
RED, /* HIGHLIGHTTEXTPEN highlighted text on BACKGROUNDPEN */
BLACK, /* BARDETAILPEN text/detail in screen-bar/menus */
WHITE, /* BARBLOCKPEN screen-bar/menus fill */
BLACK, /* BARTRIMPEN trim under screen-bar */
(UWORD) ~0 /* and used against BLOCKPEN in ASL save requesters */
};
struct ColorSpec Colours[] =
{ { 0, 0x0, 0x0, 0x0}, // black
{ 1, 0xA, 0xA, 0xA}, // light grey
{ 2, 0x3, 0x6, 0x3}, // dark green
{ 3, 0x7, 0x6, 0x3}, // dark yellow
{ 4, 0x6, 0x6, 0x6}, // medium grey
{ 5, 0x4, 0x4, 0xA}, // dark blue
{ 6, 0x8, 0x8, 0xF}, // light blue
{ 7, 0x7, 0xB, 0x7}, // light green
{ 8, 0x9, 0x3, 0x3}, // dark red
{ 9, 0x8, 0x4, 0x2}, // brown
{10, 0xF, 0x5, 0x5}, // light red
{11, 0xB, 0xB, 0x6}, // light yellow
{12, 0x3, 0x3, 0x3}, // dark grey
{13, 0xF, 0x9, 0x8}, // orange
{14, 0xF, 0x8, 0xF}, // purple
{15, 0xF, 0xF, 0xF}, // white
{16, 0x0, 0x0, 0x0},
{17, 0x1, 0x1, 0x1},
{18, 0x2, 0x2, 0x2},
{19, 0x3, 0x3, 0x3},
{20, 0x4, 0x4, 0x4},
{21, 0x5, 0x5, 0x5},
{22, 0x6, 0x6, 0x6},
{23, 0x7, 0x7, 0x7},
{24, 0x8, 0x8, 0x8},
{25, 0x9, 0x9, 0x9},
{26, 0xA, 0xA, 0xA},
{27, 0xB, 0xB, 0xB},
{28, 0xC, 0xC, 0xC},
{29, 0xD, 0xD, 0xD},
{30, 0xE, 0xE, 0xE},
{31, 0xF, 0xF, 0xF},
{-1, NULL,NULL,NULL}
};
struct TextAttr WormWars8 =
{ "WormWars.font", 8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED
}, Topaz8 =
{ "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED
};
// Start of program.
// version embedding into executable
if (0) /* that is, never */
{ say(VERSION, ANYTHING);
}
if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37L)))
{ Write(Output(), OLDKICKSTART, strlen(OLDKICKSTART));
cleanexit(EXIT_FAILURE);
}
/* From this point onwards, we can be sure we have Kickstart 2.04+... */
for (i = 0; i <= SAMPLES; i++)
{ samp[i].base = NULL;
}
enginesetup();
ProcessPtr = (struct Process *) FindTask(NULL);
if (SysBase->LibNode.lib_Version < 36L)
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Need exec.library V36+!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open graphics.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(GadToolsBase = OpenLibrary("gadtools.library", 37L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open GadTools.library V37+!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(ASLBase = OpenLibrary("asl.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open ASL.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(UtilityBase = (struct UtilityBase *) OpenLibrary("utility.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open utility.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(IconBase = OpenLibrary("icon.library", 0L)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open icon.library!\0", 24);
cleanexit(EXIT_FAILURE);
}
LowLevelBase = OpenLibrary("lowlevel.library", 0L);
ok = FALSE;
if (FileHandle = Open("PROGDIR:WormWars.config", MODE_OLDFILE))
{ if (Read(FileHandle, ConfigBuffer, CONFIGLENGTH) == CONFIGLENGTH)
{ ok = TRUE;
for (player = 0; player <= 3; player++)
{ worm[player].control = (UBYTE) ConfigBuffer[player];
}
DisplayID = (ULONG) ( (ConfigBuffer[ 4] * 16777216)
+ (ConfigBuffer[ 5] * 65536)
+ (ConfigBuffer[ 6] * 256)
+ ConfigBuffer[ 7] );
DisplayWidth = (ULONG) ( (ConfigBuffer[ 8] * 16777216)
+ (ConfigBuffer[ 9] * 65536)
+ (ConfigBuffer[10] * 256)
+ ConfigBuffer[11] );
DisplayHeight = (ULONG) ( (ConfigBuffer[12] * 16777216)
+ (ConfigBuffer[13] * 65536)
+ (ConfigBuffer[14] * 256)
+ ConfigBuffer[15] );
DisplayDepth = (UWORD) ( (ConfigBuffer[16] * 256)
+ ConfigBuffer[17] );
randomflag = (ABOOL) ConfigBuffer[18];
icons = (ABOOL) ConfigBuffer[19];
anims = (ABOOL) ConfigBuffer[20];
titlebar = (ABOOL) ConfigBuffer[21];
engraved = (ABOOL) ConfigBuffer[22];
}
Close(FileHandle);
// FileHandle = NULL;
}
/* argument parsing */
if (argc) /* started from CLI */
{ if (!(ArgsPtr = ReadArgs
( "-N=NOPRELOAD/S,-A=NOANIMS/S,-I=NOICONS/S,-P=PRI/K/N,"
"-S=SHUFFLE/S,-Q=QUIET/S,GREEN/K,RED/K,BLUE/K,YELLOW/K,FILE",
(LONG *) args,
NULL
)))
{ Printf
( "Usage: %s [-n=NOPRELOAD] [-a=NOANIMS] [-i=NOICONS] "
"[-p=PRI <priority>] [-s=SHUFFLE] [-q=QUIET] "
"[GREEN=JOY|PAD|AMIGA|NONE|KYBD] "
"[RED=JOY|PAD|AMIGA|NONE|KYBD] "
"[BLUE=JOY|PAD|AMIGA|NONE] "
"[YELLOW=JOY|PAD|AMIGA|NONE] "
"[[FILE=]<levelset>]\n",
argv[0]
);
cleanexit(EXIT_FAILURE);
}
if (args[0])
{ fxable = musicable = DEFER;
}
if (args[1])
{ anims = FALSE;
}
if (args[2])
{ icons = FALSE;
}
if (args[3])
{ if (args[3] < -128 || args[3] > 5)
{ Printf("%s: Priority range is -128 to +5\n", argv[0]);
cleanexit(EXIT_FAILURE);
}
OldPri = SetTaskPri((struct Task *) ProcessPtr, args[3]);
}
if (args[4])
{ randomflag = TRUE;
}
if (args[5])
{ quiet = TRUE;
}
for (player = 0; player <= 3; player++)
{ if (args[player + 6])
{ if
( player <= 1
&& ( (!stricmp((STRPTR) args[player + 6], "KYBD" ))
|| (!stricmp((STRPTR) args[player + 6], "KEYBOARD"))
) )
{ worm[player].control = KEYBOARD;
} elif
( (!stricmp((STRPTR) args[player + 6], "JOY" ))
|| (!stricmp((STRPTR) args[player + 6], "STICK" ))
|| (!stricmp((STRPTR) args[player + 6], "JOYSTICK"))
)
{ worm[player].control = JOYSTICK;
} elif
( (!stricmp((STRPTR) args[player + 6], "GAMEPAD"))
|| (!stricmp((STRPTR) args[player + 6], "PAD" ))
)
{ if (!LowLevelBase)
{ Printf("%s: Can't open lowlevel.library!\n", argv[0]);
cleanexit(EXIT_FAILURE);
}
worm[player].control = GAMEPAD;
} elif (!stricmp((STRPTR) args[player + 6], "AMIGA"))
{ worm[player].control = AMIGA;
} elif (!stricmp((STRPTR) args[player + 6], "NONE"))
{ worm[player].control = NONE;
} else
{ if (player <= 1)
{ Printf("%s: Worm %ld control must be JOY|PAD|AMIGA|NONE|KYBD\n", (SLONG) player, argv[0]);
} else
{ Printf("%s: Worm %ld control must be JOY|PAD|AMIGA|NONE\n", (SLONG) player, argv[0]);
}
cleanexit(EXIT_FAILURE);
} } }
if (args[10])
{ strcpy(pathname, (STRPTR) args[10]);
} }
else /* started from WB */
{ WBMsg = (struct WBStartup *) argv;
WBArg = WBMsg->sm_ArgList; /* head of the arg list */
for (i = 0;
i < WBMsg->sm_NumArgs;
i++, WBArg++)
{ if (WBArg->wa_Lock)
{ /* something that does not support locks */
parsewb();
}
else
{ /* locks supported, change to the proper directory */
OldDir = CurrentDir(WBArg->wa_Lock);
parsewb();
CurrentDir(OldDir);
}
if (i == 1)
{ strcpy(pathname, WBArg->wa_Name);
} } }
if (!(TimeValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't allocate timer value structure!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(TimerPortPtr = (struct MsgPort *) CreateMsgPort()))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't allocate timer message port!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(TimerRqPtr = (struct timerequest *) CreateIORequest(TimerPortPtr, sizeof(struct timerequest))))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create timer I/O request!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (TimerClosed = OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *) TimerRqPtr, 0))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open timer.device!\0", 24);
cleanexit(EXIT_FAILURE);
}
TimerBase = TimerRqPtr->tr_node.io_Device;
if (!ok && ASLBase->lib_Version >= 38L)
{ if (!(smr = (struct ScreenModeRequester *) AllocAslRequestTags
( ASL_ScreenModeRequest,
ASLSM_TitleText, "Worm Wars: Screen Mode Requester",
ASLSM_InitialDisplayID, HIRES_KEY | PAL_MONITOR_ID | LACE,
ASLSM_InitialDisplayWidth, ENTIREXPIXEL,
ASLSM_InitialDisplayHeight, ENTIREYPIXEL,
ASLSM_InitialDisplayDepth, DEPTH5,
ASLSM_DoWidth, TRUE,
ASLSM_DoHeight, TRUE,
ASLSM_DoDepth, TRUE,
ASLSM_MinWidth, ENTIREXPIXEL,
ASLSM_MinHeight, ENTIREYPIXEL,
ASLSM_MinDepth, DEPTH4,
TAG_DONE
)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create ASL screen mode request!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (AslRequest(smr, 0L))
{ DisplayID = smr->sm_DisplayID;
DisplayWidth = smr->sm_DisplayWidth;
DisplayHeight = smr->sm_DisplayHeight;
DisplayDepth = smr->sm_DisplayDepth;
FreeAslRequest(smr);
} else
{ FreeAslRequest(smr);
cleanexit(EXIT_SUCCESS);
} }
/* PREPARE DISPLAY -----------------------------------------------
font and screen */
if (LockPubScreen("WORMWARS"))
{ publictag = TAG_IGNORE;
} else
{ publictag = SA_PubName;
}
if
( (DiskFontBase = OpenLibrary("diskfont.library", 0L))
&& (FontPtr = (struct TextFont *) OpenDiskFont(&WormWars8))
)
{ fonttag = (ULONG) &WormWars8;
} else
{ fonttag = (ULONG) &Topaz8;
}
ScreenPtr = (struct Screen *) OpenScreenTags
( NULL,
SA_Width, DisplayWidth,
SA_Height, DisplayHeight,
SA_Depth, DisplayDepth,
SA_DisplayID, DisplayID,
SA_Behind, TRUE,
SA_AutoScroll, TRUE,
SA_ShowTitle, titlebar,
SA_Title, TITLEBAR,
SA_Colors, Colours,
SA_Font, fonttag,
SA_Pens, Pens,
publictag, "WORMWARS",
TAG_DONE
);
if (!ScreenPtr)
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open screen!\0", 24);
cleanexit(EXIT_FAILURE);
}
saveconfig = TRUE;
if (publictag == SA_PubName)
{ PubScreenStatus(ScreenPtr, NULL); // take the screen public
}
if (DisplayWidth > MAXXSIZE)
{ DisplayWidth = MAXXSIZE;
}
if (DisplayHeight > MAXYSIZE)
{ DisplayHeight = MAXYSIZE;
}
fieldx = ((DisplayWidth - 88 ) / 12) - 2;
fieldy = ((DisplayHeight - 16 - TBSIZE) / 12) - 1;
/* For some reason, we lose 4 memory chunks around this point: 2 chunks
each of 292 bytes and 10 bytes. It is related to OpenScreenTagList(),
but is not related to the SA_Colors, SA_Font or SA_Pens tags, nor to
the timer.device. Perhaps it is due to the public nature of the screen?
These must be done before the menus are set up */
if (anims)
{ NewMenu[INDEX_ANIMATIONS].nm_Flags |= CHECKED;
}
if (icons)
{ NewMenu[INDEX_CREATEICONS].nm_Flags |= CHECKED;
}
if (titlebar)
{ NewMenu[INDEX_SHOWTITLEBAR].nm_Flags |= CHECKED;
}
if (engraved)
{ NewMenu[INDEX_ENGRAVEDSQUARES].nm_Flags |= CHECKED;
}
/* GadTools */
if
( !( CycleGadget.ng_VisualInfo
= StringGadget.ng_VisualInfo
= ShuffleGadget.ng_VisualInfo
= VisualInfoPtr = (APTR) GetVisualInfo(ScreenPtr, TAG_DONE)
) )
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't get GadTools visual info!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create menus!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(LayoutMenus(MenuPtr, VisualInfoPtr, GTMN_NewLookMenus, TRUE, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't lay out menus!\0", 24);
cleanexit(EXIT_FAILURE);
}
if (!(PrevGadgetPtr = (struct Gadget *) CreateContext(&GListPtr)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools context!\0", 24);
cleanexit(EXIT_FAILURE);
}
for (player = 0; player <= 3; player++)
{ CycleGadget.ng_LeftEdge = CENTREXPIXEL - (4 * FONTX);
CycleGadget.ng_TopEdge = YSTART + 253 + (player * (FONTY + 5));
CycleGadgetPtr[player] = PrevGadgetPtr = (struct Gadget *) CreateGadget
( CYCLE_KIND,
PrevGadgetPtr,
&CycleGadget,
GTCY_Labels, CycleOptions[player],
GTCY_Active, worm[player].control,
GT_Underscore, '_',
GA_Disabled, TRUE,
TAG_DONE);
}
ShuffleGadget.ng_LeftEdge = CENTREXPIXEL + (7 * FONTX);
ShuffleGadget.ng_TopEdge = YSTART + 319;
ShuffleGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
( CHECKBOX_KIND,
PrevGadgetPtr,
&ShuffleGadget,
GTCB_Checked, randomflag,
GT_Underscore, '_',
GA_Disabled, TRUE,
TAG_DONE);
/* main window */
if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Top, 0,
WA_Width, DisplayWidth,
WA_Height, DisplayHeight,
WA_IDCMP, IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS,
WA_Gadgets, GListPtr,
WA_CustomScreen, ScreenPtr,
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_Activate, TRUE,
WA_SmartRefresh, TRUE,
WA_ReportMouse, TRUE,
WA_RptQueue, 16,
WA_NewLookMenus, TRUE,
TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open main window!\0", 24);
cleanexit(EXIT_FAILURE);
}
/* redirection of AmigaDOS system requesters */
OldWindowPtr = ProcessPtr->pr_WindowPtr;
ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, PATTERN, ASL_Window, MainWindowPtr, TAG_DONE)))
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create ASL request!\0", 24);
cleanexit(EXIT_FAILURE);
}
/* String gadgets: first the window is opened with the cycle and
checkbox gadgets.
It is necessary not to display the string gadgets yet, so the
gadgets are then created and added to the gadget list. You will note
there is no command given to render them as yet. When the attributes
are modified at highscore time, the applicable gadget is refreshed
then. */
for (which = 0; which <= HISCORES; which++)
{ StringGadget.ng_LeftEdge = CENTREXPIXEL - 85;
StringGadget.ng_TopEdge = YSTART + 133 + (which * HISCOREDISTANCE);
StringGadgetPtr[which] = PrevGadgetPtr = (struct Gadget *) CreateGadget(STRING_KIND, PrevGadgetPtr, &StringGadget, GTST_MaxChars, NAMELENGTH, STRINGA_ReplaceMode, TRUE, GA_Disabled, TRUE, TAG_DONE);
}
if (!PrevGadgetPtr)
{ DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools gadgets!\0", 24);
cleanexit(EXIT_FAILURE);
}
ScreenToFront(ScreenPtr);
if (musicable == UNTRIED)
loadthemusic();
if (fxable == UNTRIED)
loadthefx();
if (musicable == SUCCEEDED)
toggle(M);
elif (fxable == SUCCEEDED)
toggle(F);
strcpy(saystring, "Loading ");
strcat(saystring, pathname);
strcat(saystring, "...");
say(saystring, WHITE);
if (loadfields(pathname))
{ if (!quiet)
{ strcpy(saystring, "Can't open ");
strcat(saystring, pathname);
strcat(saystring, "!");
say(saystring, RED);
}
newfields();
if (!quiet)
{ anykey(TRUE);
} }
while (1)
{ titlescreen();
for (i = 0; i <= 3; i++)
{ if (worm[i].control == GAMEPAD)
{ SetJoyPortAttrs(worm[i].port, SJA_Type, SJA_TYPE_GAMECTLR, TAG_DONE);
} }
/* MAIN GAME LOOP ------------------------------------------------- */
secondsleft = secondsperlevel;
while (a == PLAYGAME)
{ millielapsed += (delay / 1000);
elapsed = millielapsed / 1000;
r++;
secondsleft = secondsperlevel - elapsed;
if (secondsleft != oldsecondsleft)
{ timeloop();
oldsecondsleft = secondsleft;
}
if (!turbo)
{ TimerRqPtr->tr_node.io_Command = TR_ADDREQUEST;
TimerRqPtr->tr_time.tv_secs = 0;
TimerRqPtr->tr_time.tv_micro = delay;
SendIO((struct IORequest *) TimerRqPtr);
evertimed = TRUE;
}
gameloop();
if (CheckIO((struct IORequest *) TimerRqPtr))
{ if (!clockdrawn)
{ draw(CLOCKICON, ICONY, CLOCK);
}
clockdrawn = TRUE;
} else
{ if (clockdrawn)
{ draw(CLOCKICON, ICONY, BLACKENED);
}
clockdrawn = FALSE;
}
WaitIO((struct IORequest *) TimerRqPtr);
} } }
EXPORT ABOOL anykey(ABOOL timeout)
{ ABOOL done = FALSE;
SBYTE count = 0;
UWORD code, qual;
ULONG class;
struct IntuiMessage* MsgPtr;
clearkybd();
Forbid();
MainWindowPtr->Flags |= WFLG_RMBTRAP;
Permit();
while (!done && !firebutton())
{ while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
GT_ReplyIMsg(MsgPtr);
switch(class)
{
case IDCMP_RAWKEY:
if ((!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
{ done = TRUE;
if (code == M)
toggle(M);
elif (code == F)
toggle(F);
elif (code == ESCAPE)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (verify())
{ cleanexit(EXIT_SUCCESS);
} else
{ Forbid();
MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
Permit();
return(FALSE);
} } } }
break;
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
break;
case IDCMP_ACTIVEWINDOW:
ignore = TRUE;
break;
case IDCMP_MOUSEBUTTONS:
if ((code == SELECTDOWN || code == MENUDOWN) && !(qual & IEQUALIFIER_REPEAT))
if (ignore)
ignore = FALSE;
else done = TRUE;
break;
case IDCMP_INTUITICKS:
if (timeout && ++count > PATIENCE)
done = TRUE;
break;
default:
break;
} } }
Forbid();
MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
Permit();
return TRUE;
}
EXPORT void celebrate(void)
{ ABOOL done = FALSE;
ULONG class;
UWORD code, qual;
struct IntuiMessage* MsgPtr;
UBYTE player;
for (player = 0; player <= 3; player++)
if (worm[player].control != NONE && worm[player].score >= worm[player].hiscore)
worm[player].hiscore = worm[player].score;
waitasec();
clearkybd();
while (!done && !firebutton)
{ while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
GT_ReplyIMsg(MsgPtr);
switch (class)
{
case IDCMP_RAWKEY:
if (code == ESCAPE)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (verify())
{ cleanexit(EXIT_SUCCESS);
} }
else
{ done = TRUE;
} }
elif (code == RETURN || code == ENTER || code == SPACEBAR)
{ done = TRUE;
} elif (code == M)
{ toggle(M);
} elif (code == F)
{ toggle(F);
}
break;
case IDCMP_MOUSEBUTTONS:
if (code == SELECTDOWN && !(qual & IEQUALIFIER_REPEAT))
{ if (ignore)
{ ignore = FALSE;
}
else
{ done = TRUE;
} }
break;
case IDCMP_ACTIVEWINDOW:
ignore = TRUE;
break;
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
break;
default:
break;
} }
draw(rand() % (fieldx + 1), rand() % (fieldy + 1), rand() % LASTOBJECT);
}
a = GAMEOVER;
}
EXPORT void cleanexit(SLONG rc)
{ SBYTE i;
BPTR FileHandle;
if (TimerRqPtr && evertimed)
{ AbortIO((struct IORequest *) TimerRqPtr);
WaitIO((struct IORequest *) TimerRqPtr);
}
freefx();
for (i = 0; i <= SAMPLES; i++)
if (samp[i].base)
FreeMem(samp[i].base, samp[i].size);
if (mode == MUSIC) StopPlayer();
for (i = 0; i <= 6; i++)
{ if (SongPtr[i])
{ UnLoadModule(SongPtr[i]);
} }
if (MEDPlayerBase) { FreePlayer();
CloseLibrary((struct Library *) MEDPlayerBase);
}
if (ASLRqPtr) FreeAslRequest(ASLRqPtr);
if (OldWindowPtr) ProcessPtr->pr_WindowPtr = OldWindowPtr;
if (MainWindowPtr) { clearkybd();
ClearMenuStrip(MainWindowPtr);
CloseWindow(MainWindowPtr);
}
if (GListPtr) FreeGadgets(GListPtr);
if (MenuPtr) FreeMenus(MenuPtr);
if (VisualInfoPtr) FreeVisualInfo(VisualInfoPtr);
if (ScreenPtr) CloseScreen(ScreenPtr);
if (FontPtr) CloseFont(FontPtr);
if (!TimerClosed) CloseDevice((struct IORequest *) TimerRqPtr);
if (TimerRqPtr) DeleteIORequest(TimerRqPtr);
if (TimerPortPtr) DeleteMsgPort(TimerPortPtr);
if (TimeValPtr) FreeMem(TimeValPtr, sizeof(struct timeval));
if (DiskFontBase) CloseLibrary((struct Library *) DiskFontBase);
if (LowLevelBase)
{ for (i = 0; i <= 3; i++)
{ SetJoyPortAttrs(worm[i].port, SJA_Reinitialize, TRUE, TAG_DONE);
}
CloseLibrary((struct Library *) LowLevelBase);
}
if (UtilityBase) CloseLibrary((struct Library *) UtilityBase);
if (ASLBase) CloseLibrary((struct Library *) ASLBase);
if (GadToolsBase) CloseLibrary((struct Library *) GadToolsBase);
if (GfxBase) CloseLibrary((struct Library *) GfxBase);
if (IconBase) CloseLibrary((struct Library *) IconBase);
if (IntuitionBase) { OpenWorkBench();
CloseLibrary((struct Library *) IntuitionBase);
}
SetTaskPri((struct Task *) ProcessPtr, OldPri);
if (ArgsPtr) FreeArgs(ArgsPtr);
if (saveconfig)
{ for (i = 0; i <= 3; i++)
{ ConfigBuffer[i] = (SBYTE) worm[i].control;
}
ConfigBuffer[ 4] = (UBYTE) (DisplayID / 16777216);
ConfigBuffer[ 5] = (UBYTE) ((DisplayID % 16777216) / 65536);
ConfigBuffer[ 6] = (UBYTE) (((DisplayID % 16777216) % 65536) / 256);
ConfigBuffer[ 7] = (UBYTE) (((DisplayID % 16777216) % 65536) % 256);
ConfigBuffer[ 8] = (UBYTE) (DisplayWidth / 16777216);
ConfigBuffer[ 9] = (UBYTE) ((DisplayWidth % 16777216) / 65536);
ConfigBuffer[10] = (UBYTE) (((DisplayWidth % 16777216) % 65536) / 256);
ConfigBuffer[11] = (UBYTE) (((DisplayWidth % 16777216) % 65536) % 256);
ConfigBuffer[12] = (UBYTE) (DisplayHeight / 16777216);
ConfigBuffer[13] = (UBYTE) ((DisplayHeight % 16777216) / 65536);
ConfigBuffer[14] = (UBYTE) (((DisplayHeight % 16777216) % 65536) / 256);
ConfigBuffer[15] = (UBYTE) (((DisplayHeight % 16777216) % 65536) % 256);
ConfigBuffer[16] = (UBYTE) (DisplayDepth / 65536); // the DisplayDepth bytes are not used any more
ConfigBuffer[17] = (UBYTE) (DisplayDepth % 65536);
ConfigBuffer[18] = (UBYTE) randomflag;
ConfigBuffer[19] = (UBYTE) icons;
ConfigBuffer[20] = (UBYTE) anims;
ConfigBuffer[21] = (UBYTE) titlebar;
ConfigBuffer[22] = (UBYTE) engraved;
if (FileHandle = Open("PROGDIR:WormWars.config", MODE_NEWFILE))
{ Write(FileHandle, ConfigBuffer, CONFIGLENGTH);
Close(FileHandle);
// FileHandle = NULL;
} }
exit(rc); /* End of program. */
}
EXPORT void clearkybd(void)
{ struct IntuiMessage* MsgPtr;
while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
GT_ReplyIMsg(MsgPtr);
}
EXPORT void effect(SBYTE index)
{ AUTO SBYTE i;
AUTO SBYTE ok = -1;
AUTO ULONG oldestreceipt = (ULONG) -1L;
PERSIST ULONG nextreceipt = 1L;
/* oldestreceipt = temporary variable for ascertaining oldest
sound still playing.
nextreceipt = next unused receipt number (monotonically incrementing). */
if (mode == FX)
{ for (i = 0; i <= 3; i++)
{ /* decide on a channel */
if (ok == -1)
{ if (!eversent[i])
{ ok = i;
} elif (CheckIO((struct IORequest *) AudioRqPtr[i]))
{ WaitIO((struct IORequest *) AudioRqPtr[i]);
ok = i;
} } }
if (ok == -1)
{ for (i = 0; i <= 3; i++)
if (receipter[i] < oldestreceipt)
{ ok = i;
oldestreceipt = receipter[i];
}
AbortIO((struct IORequest *) AudioRqPtr[ok]);
WaitIO((struct IORequest *) AudioRqPtr[ok]);
}
eversent[ok] = TRUE;
AudioRqPtr[ok]->ioa_Cycles = 1;
AudioRqPtr[ok]->ioa_Request.io_Command = CMD_WRITE;
AudioRqPtr[ok]->ioa_Request.io_Flags = ADIOF_PERVOL;
AudioRqPtr[ok]->ioa_Request.io_Unit = (struct Unit *) (1 << ok);
AudioRqPtr[ok]->ioa_Volume = samp[index].volume;
AudioRqPtr[ok]->ioa_Period = (UWORD) samp[index].speed;
AudioRqPtr[ok]->ioa_Request.io_Message.mn_ReplyPort
= AudioPortPtr[ok];
AudioRqPtr[ok]->ioa_Data = (UBYTE *) samp[index].base;
AudioRqPtr[ok]->ioa_Length = samp[index].length[samp[index].bank];
BeginIO((struct IORequest *) AudioRqPtr[ok]);
receipter[ok] = nextreceipt;
} }
EXPORT void help(UBYTE type)
{ TEXT title[10], tempstring[12];
SWORD x, y;
UBYTE i;
effect(FXHELP);
if (type == ORB)
{ strcpy(title, "Creatures");
x = 172;
y = 28 + ((CREATUREHELPS + 1) * SQUAREY);
} else
{ strcpy(title, "Objects");
x = 320;
y = 32 + (LASTOBJECT * SQUAREY);
}
if (!(HelpWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, (DisplayWidth / 2) - (x / 2),
WA_Top, (DisplayHeight / 2) - (y / 2),
WA_Width, x,
WA_Height, y,
WA_IDCMP, IDCMP_CLOSEWINDOW |
IDCMP_RAWKEY |
IDCMP_MOUSEBUTTONS |
IDCMP_INTUITICKS,
WA_Title, title,
WA_Gadgets, NULL,
WA_CustomScreen, ScreenPtr,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
TAG_DONE)))
{ say("Can't open help window!", RED);
anykey(TRUE);
} else
{ SetAPen(HelpWindowPtr->RPort, WHITE);
if (type == ORB)
{ Move(HelpWindowPtr->RPort, 26 + (14 * FONTX), 20);
Text(HelpWindowPtr->RPort, "Pts", 3);
Move(HelpWindowPtr->RPort, 26, 22);
Draw(HelpWindowPtr->RPort, 160, 22);
for (i = 0; i <= CREATUREHELPS; i++)
{ Image.ImageData = ImageData[creaturehelp[i].image];
DrawImage
( HelpWindowPtr->RPort,
&Image,
10,
22 + (i * SQUAREY)
);
Move(HelpWindowPtr->RPort, 26 , 31 + (i * SQUAREY));
Text(HelpWindowPtr->RPort, creaturehelp[i].desc, strlen(creaturehelp[i].desc));
if
( creaturehelp[i].image == LASTPROTECTOR
|| creaturehelp[i].image == LASTHEAD
|| creaturehelp[i].image == SLIME
)
{ stcl_d(tempstring, 0);
} else
{ assert(creaturehelp[i].image - FIRSTCREATURE >= FIRSTCREATURE && creaturehelp[i].image - FIRSTCREATURE <= LASTCREATURE);
stcl_d(tempstring, creatureinfo[creaturehelp[i].image - FIRSTCREATURE].score);
}
align(tempstring, 3, ' ');
Move(HelpWindowPtr->RPort, 26 + (14 * 8), 31 + (i * SQUAREY));
Text(HelpWindowPtr->RPort, tempstring, 3);
} }
else
{ assert(type == AFFIXER);
for (i = 0; i <= LASTOBJECT; i++)
{ Image.ImageData = ImageData[i];
Move(HelpWindowPtr->RPort, 26, 24 + (i * SQUAREY));
DrawImage
( HelpWindowPtr->RPort,
&Image,
10,
15 + (i * SQUAREY)
);
Text(HelpWindowPtr->RPort, objectdesc[i], strlen(objectdesc[i]));
} }
helploop(type);
} }
EXPORT void helpabout(void)
{ SBYTE line;
SLONG projectval;
TEXT projectstring[7], ks[5] = " ", wb[5] = " ";
ULONG ksval = SysBase->LibNode.lib_Version,
wbval = IconBase->lib_Version;
effect(FXHELP);
if (!(HelpWindowPtr = (struct Window *) OpenWindowTags(NULL,
WA_Left, (DisplayWidth / 2) - (ABOUTXPIXEL / 2),
WA_Top, (DisplayHeight / 2) - (ABOUTYPIXEL / 2),
WA_Width, ABOUTXPIXEL,
WA_Height, ABOUTYPIXEL,
WA_IDCMP, IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
WA_Title, "About Worm Wars",
WA_Gadgets, NULL,
WA_CustomScreen, ScreenPtr,
WA_DragBar, TRUE,
WA_CloseGadget, TRUE,
WA_NoCareRefresh, TRUE,
WA_Activate, TRUE,
TAG_DONE)))
{ say("Can't open About... window!", RED);
anykey(TRUE);
} else
{ /* calculate project size */
projectval =
10 // header
+ ((HISCORES + 1) * HISCORESIZE) // high scores
+ ((levels + 1) * (8 + (LEVELSIZE))) // level data
+ strlen(VERSION); // version string
switch(ksval)
{
case 37:
strcpy(ks, "2.04");
break;
case 38:
strcpy(ks, "2.1 ");
break;
case 39:
strcpy(ks, "3.0 ");
break;
case 40:
case 41:
case 42:
case 43:
strcpy(ks, "3.1 ");
break;
case 44:
strcpy(ks, "3.5 ");
break;
case 45:
strcpy(ks, "3.9 ");
break;
default:
strcpy(ks, "4.0+");
break;
}
switch(wbval)
{
case 37:
strcpy(wb, "2.04");
break;
case 38:
strcpy(wb, "2.1 ");
break;
case 39:
strcpy(wb, "3.0 ");
break;
case 40:
case 41:
case 42:
case 43:
strcpy(wb, "3.1 ");
break;
case 44:
strcpy(wb, "3.5 ");
break;
case 45:
strcpy(wb, "3.9 ");
break;
default:
strcpy(wb, "4.0+");
break;
}
SetAPen(HelpWindowPtr->RPort, worm[rand() % 4].colour);
RectFill(HelpWindowPtr->RPort, 8, 13, ABOUTXPIXEL - 11, ABOUTYPIXEL - 6);
SetAPen(HelpWindowPtr->RPort, ABOUTSHADOW);
Move(HelpWindowPtr->RPort, 7, ABOUTYPIXEL - 5);
Draw(HelpWindowPtr->RPort, 7, 12);
Draw(HelpWindowPtr->RPort, ABOUTXPIXEL - 10, 12);
SetAPen(HelpWindowPtr->RPort, ABOUTSHINE);
Draw(HelpWindowPtr->RPort, ABOUTXPIXEL - 10, ABOUTYPIXEL - 5);
Draw(HelpWindowPtr->RPort, 8, ABOUTYPIXEL - 5);
SetAPen(HelpWindowPtr->RPort, BLACK);
SetDrMd(HelpWindowPtr->RPort, JAM1);
for (line = 0; line <= ABOUTLINES; line++)
{ Move(HelpWindowPtr->RPort, about[line].x, about[line].y);
Text(HelpWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
}
stcl_d(projectstring, projectval);
align(projectstring, 6, ' ');
Move(HelpWindowPtr->RPort, PROJECTX, PROJECTY);
Text(HelpWindowPtr->RPort, projectstring, 6);
Move(HelpWindowPtr->RPort, KICKSTARTX, KICKSTARTY);
Text(HelpWindowPtr->RPort, ks, 4);
Move(HelpWindowPtr->RPort, WORKBENCHX, WORKBENCHY);
Text(HelpWindowPtr->RPort, wb, 4);
DrawBevelBox(HelpWindowPtr->RPort, 16, 20, 44 + 4, 38 + 4, GT_VisualInfo, VisualInfoPtr, GTBB_Recessed, TRUE, TAG_END);
drawabout();
helploop(NOSQUARE);
} }
EXPORT void helploop(UBYTE type)
{ ABOOL done = FALSE;
UBYTE objx, objy;
UWORD code, qual;
SWORD mousex, mousey;
SBYTE birdframe = -1, birddir = 1;
ULONG class;
struct IntuiMessage* MsgPtr;
while(!done)
{ Wait(1L << HelpWindowPtr->UserPort->mp_SigBit);
while (MsgPtr = (struct IntuiMessage *) GetMsg(HelpWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
mousex = MsgPtr->MouseX;
mousey = MsgPtr->MouseY;
ReplyMsg((struct Message *) MsgPtr);
switch(class)
{
case IDCMP_INTUITICKS:
if (type == ORB && anims)
{ birdframe += birddir;
Image.ImageData = ImageData[birdframes[birdframe]];
DrawImage
( HelpWindowPtr->RPort,
&Image,
10,
46
);
if (birdframe == 0)
{ birddir = 1;
} elif (birdframe == 4)
{ birddir = -1;
} }
break;
case IDCMP_CLOSEWINDOW:
done = TRUE;
break;
case IDCMP_RAWKEY:
if (code == SPACEBAR || code == RETURN || code == ENTER || code == HELP)
done = TRUE;
elif (code == ESCAPE)
{ if (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
{ if (verify())
{ CloseWindow(HelpWindowPtr);
cleanexit(EXIT_SUCCESS);
} }
else done = TRUE;
}
break;
case IDCMP_MOUSEBUTTONS:
if (a == FIELDEDIT && type == AFFIXER)
{ objx = (mousex - 10) / 328; // which column
objy = (mousey - 13) / 10; // which row
if ((objx == 0 || objx == 1) && (objy >= 0 && objy <= LASTOBJECT / 2))
{ if (objx)
setbrush(objy + 1 + (LASTOBJECT / 2));
else setbrush(objy);
done = TRUE;
} }
break;
default:
break;
} } }
CloseWindow(HelpWindowPtr);
HelpWindowPtr = NULL;
clearkybd();
}
EXPORT void filedelete(void)
{ TEXT newpathname[255], temp1[81];
if (AslRequestTags(ASLRqPtr, ASL_Hail, "Delete Levelset", ASL_FuncFlags, FILF_PATGAD | FILF_SAVE, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
{ strcpy(newpathname, ASLRqPtr->rf_Dir);
AddPart(newpathname, ASLRqPtr->rf_File, 254);
if (DeleteFile(newpathname))
{ strcpy(temp1, "Deleted ");
strcat(temp1, newpathname);
strcat(temp1, ".");
} else
{ strcpy(temp1, "Couldn't delete ");
strcat(temp1, newpathname);
strcat(temp1, "!");
}
say(temp1, WHITE);
} }
EXPORT void fileopen(ABOOL revert)
{ TEXT temp1[81],
temp2[3],
newpathname[255];
strcpy(temp1, "Opened ");
strcpy(newpathname, pathname);
if (revert || (AslRequestTags(ASLRqPtr, ASL_Hail, "Open Levelset", ASL_FuncFlags, FILF_PATGAD, TAG_DONE) && *(ASLRqPtr->rf_File)))
{ if (!revert)
{ strcpy(newpathname, ASLRqPtr->rf_Dir);
AddPart(newpathname, ASLRqPtr->rf_File, 254);
}
if (!loadfields(newpathname))
{ strcpy(pathname, newpathname);
strcat(temp1, pathname);
strcat(temp1, " (");
stci_d(temp2, levels);
strcat(temp1, temp2);
strcat(temp1, " levels).");
say(temp1, WHITE);
if (a == FIELDEDIT)
turborender();
else hiscores();
} else
{ strcpy(temp1, "Couldn't open ");
strcat(temp1, newpathname);
strcat(temp1, "!");
say(temp1, WHITE);
} }
if (a == GAMEOVER)
anykey(TRUE);
}
EXPORT void filesaveas(ABOOL flag)
{ ABOOL cont = TRUE;
TEXT newpathname[255], temp1[SAYLIMIT + 1], temp2[3];
struct DiskObject* InfoHandle;
/* flag is TRUE for 'save as...', FALSE for 'save'. */
strcpy(newpathname, pathname);
if (flag)
if (AslRequestTags(ASLRqPtr, ASL_Hail, "Save Levelset", ASL_FuncFlags, FILF_PATGAD | FILF_SAVE, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
{ strcpy(newpathname, ASLRqPtr->rf_Dir);
AddPart(newpathname, ASLRqPtr->rf_File, 254);
} else cont = FALSE;
if (cont)
{ strcpy(temp1, "Saving ");
strcat(temp1, newpathname);
strcat(temp1, "...");
say(temp1, WHITE);
if (savefields(newpathname))
{ strcpy(pathname, newpathname);
if (icons)
{ InfoHandle = GetDiskObjectNew(DEFAULTSET);
InfoHandle->do_CurrentX = NO_ICON_POSITION;
InfoHandle->do_CurrentY = NO_ICON_POSITION;
if (!PutDiskObject(pathname, InfoHandle))
{ say("Couldn't write .info file!", RED);
anykey(TRUE);
} }
strcpy(temp1, "Saved ");
strcat(temp1, pathname);
strcat(temp1, " (");
stci_d(temp2, levels);
strcat(temp1, temp2);
strcat(temp1, " levels).");
} else
{ strcpy(temp1, "Couldn't save ");
strcat(temp1, newpathname);
strcat(temp1, "!");
}
say(temp1, WHITE);
if (a == GAMEOVER)
anykey(TRUE);
} }
EXPORT void gameinput(void)
{ ABOOL allowed = TRUE,
done;
UWORD code,
qual = 0; // to avoid spurious compiler warnings
ULONG class;
struct IntuiMessage* MsgPtr;
SBYTE keyplayer, i;
UBYTE which;
for (which = 0; which <= NUMKEYS; which++)
key[which].down = FALSE;
/* keyboard */
while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
ReplyMsg((struct Message *) MsgPtr);
if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)))
{ if (code < KEYUP)
{ switch(code)
{
case M:
toggle(M);
break;
case F:
toggle(F);
break;
case KEY_T:
// check whether any human worms are playing
for (i = 0; i <= 3; i++)
{ if
( worm[i].control != AMIGA
&& worm[i].control != NONE
&& worm[i].lives
)
{ allowed = FALSE;
break;
} }
if (allowed)
{ if (turbo)
{ turbo = FALSE;
} else
{ turbo = TRUE;
draw(CLOCKICON, ICONY, CLOCK);
} }
break;
case P:
clearkybd();
say("Paused...press P to unpause", WHITE);
done = FALSE;
while (!done)
{ Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
ReplyMsg((struct Message *) MsgPtr);
if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)))
{ if (code == ESCAPE)
{ if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (verify())
cleanexit(EXIT_SUCCESS);
} else
{ a = GAMEOVER;
done = TRUE;
worm[0].lives = worm[1].lives = worm[2].lives = worm[3].lives = 0;
} }
elif (code == M)
toggle(M);
elif (code == F)
toggle(F);
elif (code == P)
{ say("Unpaused", WHITE);
done = TRUE;
} } } }
break;
case ESCAPE:
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (verify())
cleanexit(EXIT_SUCCESS);
} else
{ a = GAMEOVER;
worm[0].lives = worm[1].lives = worm[2].lives = worm[3].lives = 0;
}
break;
default:
for (which = 0; which <= NUMKEYS; which++)
if (code == key[which].scancode)
key[which].down = TRUE;
break;
} } }
elif (class == IDCMP_CLOSEWINDOW)
cleanexit(EXIT_SUCCESS);
elif (class == IDCMP_REFRESHWINDOW)
{ GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
} }
for (which = 0; which <= NUMKEYS; which++)
{ if (key[which].down)
{ if (key[which].special == ONEHUMAN)
{ if
( (worm[0].control == KEYBOARD && worm[1].control != KEYBOARD)
)
{ wormqueue(0, key[which].deltax, key[which].deltay);
} elif
( (worm[1].control == KEYBOARD && worm[0].control != KEYBOARD)
)
{ wormqueue(1, key[which].deltax, key[which].deltay);
} }
elif (key[which].special == MOVE || key[which].special == AMMO)
{ if (worm[key[which].player].control == KEYBOARD)
{ keyplayer = key[which].player;
} elif
( key[which].player == 1
&& (worm[0].control == KEYBOARD && worm[1].control != KEYBOARD)
)
{ keyplayer = 0;
} elif
( key[which].player == 0
&& (worm[1].control == KEYBOARD && worm[0].control != KEYBOARD)
)
{ keyplayer = 1;
} else keyplayer = -1;
if (keyplayer != -1)
{ wormqueue(keyplayer, key[which].deltax, key[which].deltay);
} }
else
{ assert(key[which].special == TRAINER);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ train(key[which].scancode, TRUE);
} else
{ train(key[which].scancode, FALSE);
} } } } }
EXPORT void hiscores(void)
{ SBYTE which;
TEXT tempstring[NAMELENGTH + 1];
/* render hiscores
#################################################### # = shadow
# # # # # # % % = shine
# # # # # # %
# # # # # # %
# # # # # # %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
hiframe = 0;
SetDrMd(MainWindowPtr->RPort, JAM1);
for (which = 0; which <= HISCORES; which++)
{ if (hiscore[which].player == -1)
SetAPen(MainWindowPtr->RPort, LIGHTGREY);
else SetAPen(MainWindowPtr->RPort, worm[hiscore[which].player].colour);
RectFill
( MainWindowPtr->RPort,
CENTREXPIXEL - 216,
YSTART + 134 + (which * HISCOREDISTANCE),
CENTREXPIXEL + 216,
YSTART + 143 + (which * HISCOREDISTANCE)
);
if (hiscore[which].player == 0)
SetAPen(MainWindowPtr->RPort, DARKGREEN);
elif (hiscore[which].player == 1)
SetAPen(MainWindowPtr->RPort, DARKRED);
elif (hiscore[which].player == 2)
SetAPen(MainWindowPtr->RPort, DARKBLUE);
elif (hiscore[which].player == 3)
SetAPen(MainWindowPtr->RPort, DARKYELLOW);
else SetAPen(MainWindowPtr->RPort, DARKGREY);
Move(MainWindowPtr->RPort, CENTREXPIXEL - 217, YSTART + 144 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL - 217, YSTART + 133 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL + 217, YSTART + 133 + (which * HISCOREDISTANCE));
if (hiscore[which].player != -1)
{ /* divider bars */
Move(MainWindowPtr->RPort, CENTREXPIXEL - 193, YSTART + 133 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL - 193, YSTART + 143 + (which * HISCOREDISTANCE));
Move(MainWindowPtr->RPort, CENTREXPIXEL - 121, YSTART + 133 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL - 121, YSTART + 143 + (which * HISCOREDISTANCE));
Move(MainWindowPtr->RPort, CENTREXPIXEL - 85, YSTART + 133 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL - 85, YSTART + 143 + (which * HISCOREDISTANCE));
Move(MainWindowPtr->RPort, CENTREXPIXEL + 92, YSTART + 133 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL + 92, YSTART + 143 + (which * HISCOREDISTANCE));
Move(MainWindowPtr->RPort, CENTREXPIXEL + 142, YSTART + 133 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL + 142, YSTART + 143 + (which * HISCOREDISTANCE));
}
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, CENTREXPIXEL - 217, YSTART + 144 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL + 217, YSTART + 144 + (which * HISCOREDISTANCE));
Draw(MainWindowPtr->RPort, CENTREXPIXEL + 217, YSTART + 134 + (which * HISCOREDISTANCE));
SetAPen(MainWindowPtr->RPort, BLACK);
if (hiscore[which].player != -1)
{ stci_d(tempstring, which + 1);
tempstring[1] = '.';
Move(MainWindowPtr->RPort, CENTREXPIXEL - 214, YSTART + 141 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, tempstring, 2);
stci_d(tempstring, hiscore[which].score);
align(tempstring, 7, ' ');
Move(MainWindowPtr->RPort, CENTREXPIXEL - 182, YSTART + 141 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, tempstring, 7);
if (hiscore[which].level == -1)
{ strcpy(tempstring, "All");
} else
{ stci_d(tempstring, hiscore[which].level);
align(tempstring, 3, ' ');
}
Move(MainWindowPtr->RPort, CENTREXPIXEL - 114, YSTART + 141 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, tempstring, 3);
Move(MainWindowPtr->RPort, CENTREXPIXEL - 79, YSTART + 141 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, hiscore[which].name, strlen(hiscore[which].name));
Move(MainWindowPtr->RPort, CENTREXPIXEL + 98, YSTART + 141 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, hiscore[which].time, strlen(hiscore[which].time));
Move(MainWindowPtr->RPort, CENTREXPIXEL + 148, YSTART + 141 + (which * HISCOREDISTANCE));
Text(MainWindowPtr->RPort, hiscore[which].date, strlen(hiscore[which].date));
Image.ImageData = ImageData[missileframes[hiscore[which].player][0]];
DrawImage(MainWindowPtr->RPort, &Image, CENTREXPIXEL + 220, YSTART + 133 + (which * HISCOREDISTANCE));
} }
SetDrMd(MainWindowPtr->RPort, JAM2);
}
EXPORT void hiscorenames(void)
{ ULONG class;
ABOOL done;
SBYTE which;
struct IntuiMessage* MsgPtr;
for (which = 0; which <= HISCORES; which++)
{ if (hiscore[which].fresh)
{ GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, FALSE, GTST_String, worm[hiscore[which].player].name, TAG_DONE);
ActivateGadget(StringGadgetPtr[which], MainWindowPtr, NULL);
done = FALSE;
while (!done)
{ while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
GT_ReplyIMsg(MsgPtr);
if (class == IDCMP_GADGETUP)
{ done = TRUE;
} elif (class == IDCMP_MOUSEBUTTONS)
{ ActivateGadget(StringGadgetPtr[which], MainWindowPtr, NULL);
} elif (class == IDCMP_REFRESHWINDOW)
{ GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
} } }
GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
effect(FXAPPLAUSE);
strcpy(hiscore[which].name, ((struct StringInfo *) (StringGadgetPtr[which]->SpecialInfo))->Buffer);
if (hiscore[which].name[0] >= 'a' && hiscore[which].name[0] <= 'z')
{ hiscore[which].name[0] -= 32;
}
strcpy(worm[hiscore[which].player].name, hiscore[which].name);
hiscore[which].fresh = FALSE;
hiscores();
} } }
EXPORT void resettime(void)
{ millielapsed = 0;
GetSysTime(TimeValPtr);
srand((UWORD) TimeValPtr->tv_micro);
}
EXPORT void systemrundown(SBYTE player, UBYTE multiply)
{ FLAG done = FALSE;
TEXT tempstring[6];
SBYTE i;
UWORD code, qual;
ULONG class;
struct IntuiMessage* MsgPtr;
PERSIST TEXT runstring[5][RUNSTRINGLENGTH + 1] =
{" Level Bonus: ## x #### =",
"Number Bonus: ## x #### =",
" Time Bonus: #:## x #### =",
" Dim Bonus: ## x #### =",
" Glow Bonus: ## x #### ="};
DrawBevelBox(MainWindowPtr->RPort, RUNDOWNX, RUNDOWNY, 304, 66, GT_VisualInfo, VisualInfoPtr, TAG_END);
SetAPen(MainWindowPtr->RPort, BLACK);
RectFill
( MainWindowPtr->RPort,
RUNDOWNX + 1,
RUNDOWNY + 1,
RUNDOWNX + 302,
RUNDOWNY + 64
);
SetAPen(MainWindowPtr->RPort, worm[player].colour);
Image.ImageData = ImageData[TREASURE];
DrawImage(MainWindowPtr->RPort, &Image, RUNDOWNX + 8, RUNDOWNY + 3);
if (worm[player].numbers == 0)
{ Image.ImageData = ImageData[FIRSTPAIN + player];
} else
{ Image.ImageData = ImageData[FIRSTNUMBER + worm[player].numbers - 1];
}
DrawImage(MainWindowPtr->RPort, &Image, RUNDOWNX + 8, RUNDOWNY + 3 + SQUAREY );
Image.ImageData = ImageData[CLOCK];
DrawImage(MainWindowPtr->RPort, &Image, RUNDOWNX + 8, RUNDOWNY + 3 + (SQUAREY * 2));
Image.ImageData = ImageData[FIRSTTAIL + player];
DrawImage(MainWindowPtr->RPort, &Image, RUNDOWNX + 8, RUNDOWNY + 3 + (SQUAREY * 3));
Image.ImageData = ImageData[FIRSTGLOW + player];
DrawImage(MainWindowPtr->RPort, &Image, RUNDOWNX + 8, RUNDOWNY + 3 + (SQUAREY * 4));
for (i = 0; i <= 4; i++)
{ Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_1ST, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * i));
Text(MainWindowPtr->RPort, runstring[i], RUNSTRINGLENGTH);
if (i == 2)
{ tempstring[0] = 48 + (quantity[2][0] / 60);
tempstring[1] = ':';
tempstring[2] = 48 + ((quantity[2][0] % 60) / 10);
tempstring[3] = 48 + ((quantity[2][0] % 60) % 10);
} else
{ stci_d(tempstring, quantity[i][0]);
align(tempstring, 4, ' ');
}
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_2ND, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * i));
Text(MainWindowPtr->RPort, tempstring, 4);
stci_d(tempstring, quantity[i][1]);
align(tempstring, 4, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_3RD, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * i));
Text(MainWindowPtr->RPort, tempstring, 4);
}
while (!done)
{ while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
{ class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
ReplyMsg((struct Message *) MsgPtr);
if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP)
{ done = TRUE;
} }
if (done)
{ wormscore
( player,
(quantity[0][2] + quantity[1][2] + quantity[2][2] + quantity[3][2] + quantity[4][2]) / multiply
);
quantity[0][2] =
quantity[1][2] =
quantity[2][2] =
quantity[3][2] =
quantity[4][2] = 0;
}
done = TRUE;
for (i = 0; i <= 4; i++)
{ stci_d(tempstring, quantity[i][2]);
align(tempstring, 5, ' ');
Move(MainWindowPtr->RPort, RUNDOWNX + RUNDOWNX_4TH, RUNDOWNY + RUNDOWNY_2ND + (SQUAREY * i));
Text(MainWindowPtr->RPort, tempstring, 5);
if (quantity[i][2])
{ if (quantity[i][2] >= multiply * 2)
{ quantity[i][2] -= multiply * 2;
wormscore(player, 2);
} else
{ quantity[i][2] -= multiply;
wormscore(player, 1);
}
done = FALSE;
} }
effect(FXCLICK);
} }
EXPORT void say(STRPTR sentence, COLOUR colour)
{ SWORD length = (SBYTE) strlen(sentence),
centrex;
centrex = STARTXPIXEL + ((ENDXPIXEL - STARTXPIXEL) / 2);
/* truncate text */
if (length > SAYLIMIT)
{ *(sentence + SAYLIMIT) = 0;
length = SAYLIMIT;
}
/* clear areas to left and right of text, respectively */
SetAPen(MainWindowPtr->RPort, BLACK);
RectFill
( MainWindowPtr->RPort,
STARTXPIXEL,
TBSIZE + 4,
centrex - (length * FONTX / 2),
TBSIZE + 15
);
RectFill
( MainWindowPtr->RPort,
centrex + (length * FONTX / 2) + 1,
TBSIZE + 4,
ENDXPIXEL,
TBSIZE + 15
);
/* render shadow text */
SetAPen(MainWindowPtr->RPort, MEDIUMGREY);
Move(MainWindowPtr->RPort, centrex - (length * FONTX / 2) + 1, TBSIZE + FONTY + 3);
Text(MainWindowPtr->RPort, sentence, length);
/* render actual text */
SetDrMd(MainWindowPtr->RPort, JAM1);
SetAPen(MainWindowPtr->RPort, colour);
Move(MainWindowPtr->RPort, centrex - (length * FONTX / 2), TBSIZE + FONTY + 3);
Text(MainWindowPtr->RPort, sentence, length);
SetDrMd(MainWindowPtr->RPort, JAM2);
}
EXPORT void printstat(SBYTE player, SBYTE theline)
{ Move
( MainWindowPtr->RPort,
FONTX * 3,
STARTYPIXEL + (player * SQUAREX * 10) + 8 + (theline * SQUAREY)
);
Text(MainWindowPtr->RPort, stattext, 7);
}
EXPORT void stopfx(void)
{ SBYTE i;
for (i = 0; i <= 3; i++)
{ if (eversent[i] && AudioRqPtr[i])
{ AbortIO((struct IORequest *) AudioRqPtr[i]);
WaitIO((struct IORequest *) AudioRqPtr[i]);
} } }
EXPORT void titlescreen(void)
{ SBYTE player, i;
ULONG class;
UWORD code, qual;
TEXT tempstring[8];
struct IntuiMessage* MsgPtr;
struct Gadget* WhichGadgetPtr;
struct MenuItem* ItemPtr;
Forbid();
MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
Permit();
clearscreen();
SetDrMd(MainWindowPtr->RPort, JAM2);
drawlogo();
SetMenuStrip(MainWindowPtr, MenuPtr);
for (player = 0; player <= 3; player++)
{ GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
}
GT_SetGadgetAttrs(ShuffleGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
SetDrMd(MainWindowPtr->RPort, JAM1);
strcpy(tempstring, "Worm :");
for (player = 0; player <= 3; player++)
{ tempstring[5] = '1' + player;
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (12 * FONTX) + 1, YSTART + 263 + (player * (FONTY + 5)));
Text(MainWindowPtr->RPort, tempstring, 7);
Move(MainWindowPtr->RPort, CENTREXPIXEL - ( 7 * FONTX) + 1, YSTART + 264 + (player * (FONTY + 5)));
Text(MainWindowPtr->RPort, "_", 1);
SetAPen(MainWindowPtr->RPort, worm[player].colour);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (12 * FONTX), YSTART + 262 + (player * (FONTY + 5)));
Text(MainWindowPtr->RPort, tempstring, 7);
Move(MainWindowPtr->RPort, CENTREXPIXEL - ( 7 * FONTX), YSTART + 263 + (player * (FONTY + 5)));
Text(MainWindowPtr->RPort, "_", 1);
}
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (10 * FONTX) + 1, YSTART + 328);
Text(MainWindowPtr->RPort, "Shuffle Levels?", 15);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (10 * FONTX) + 1, YSTART + 329);
Text(MainWindowPtr->RPort, "_", 1);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (18 * FONTX / 2) + 1, YSTART + 225);
Text(MainWindowPtr->RPort, "RETURN: Start Game", 18);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (22 * FONTX / 2) + 1, YSTART + 235);
Text(MainWindowPtr->RPort, "Spacebar: Level Editor", 22);
SetAPen(MainWindowPtr->RPort, WHITE);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (10 * FONTX), YSTART + 327);
Text(MainWindowPtr->RPort, "Shuffle Levels?", 15);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (10 * FONTX), YSTART + 328);
Text(MainWindowPtr->RPort, "_", 1);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (18 * FONTX / 2), YSTART + 224);
Text(MainWindowPtr->RPort, "RETURN: Start Game", 18);
Move(MainWindowPtr->RPort, CENTREXPIXEL - (22 * FONTX / 2), YSTART + 234);
Text(MainWindowPtr->RPort, "Spacebar: Level Editor", 22);
clearkybd();
hiscores();
hiscorenames();
playsong(0);
do
{ Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
{ WhichGadgetPtr = (struct Gadget *) MsgPtr->IAddress;
class = MsgPtr->Class;
code = MsgPtr->Code;
qual = MsgPtr->Qualifier;
GT_ReplyIMsg(MsgPtr);
switch (class)
{
case IDCMP_RAWKEY:
if (!(qual & IEQUALIFIER_REPEAT))
{ switch (code)
{
case F:
toggle(F);
break;
case M:
toggle(M);
break;
case SPACEBAR:
a = FIELDEDIT;
break;
case F1:
case ALPHAONE:
case NUMERICONE:
effect(FXCLICK);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (--worm[0].control < 0)
worm[0].control = 4;
} else
{ if (++worm[0].control > 4)
worm[0].control = 0;
}
GT_SetGadgetAttrs(CycleGadgetPtr[0], MainWindowPtr, NULL, GTCY_Active, worm[0].control, TAG_DONE);
break;
case F2:
case ALPHATWO:
case NUMERICTWO:
effect(FXCLICK);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (--worm[1].control < 0)
worm[1].control = 4;
} else
{ if (++worm[1].control > 4)
worm[1].control = 0;
}
GT_SetGadgetAttrs(CycleGadgetPtr[1], MainWindowPtr, NULL, GTCY_Active, worm[1].control, TAG_DONE);
break;
case F3:
case ALPHATHREE:
case NUMERICTHREE:
effect(FXCLICK);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (worm[2].control > 0)
{ worm[2].control--;
} else worm[2].control = 3;
} else
{ if (worm[2].control < 3)
{ worm[2].control++;
} else worm[2].control = 0;
}
GT_SetGadgetAttrs(CycleGadgetPtr[2], MainWindowPtr, NULL, GTCY_Active, worm[2].control, TAG_DONE);
break;
case F4:
case ALPHAFOUR:
case NUMERICFOUR:
effect(FXCLICK);
if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
{ if (--worm[3].control < 0)
worm[3].control = 3;
} else
{ if (++worm[3].control > 3)
worm[3].control = 0;
}
GT_SetGadgetAttrs(CycleGadgetPtr[3], MainWindowPtr, NULL, GTCY_Active, worm[3].control, TAG_DONE);
break;
case RETURN:
case ENTER:
a = PLAYGAME;
break;
case S:
randomflag = !randomflag;
GT_SetGadgetAttrs(ShuffleGadgetPtr, MainWindowPtr, NULL, GTCB_Checked, randomflag, TAG_DONE);
break;
case ESCAPE:
if (verify())
cleanexit(EXIT_SUCCESS);
break;
case HELP:
helpabout();
break;
default:
break;
} }
break;
case IDCMP_MENUPICK:
while (code != MENUNULL)
{ ItemPtr = ItemAddress(MenuPtr, code);
switch (MENUNUM(code))
{
case MN_PROJECT:
switch (ITEMNUM(code))
{
case IN_NEW:
newfields();
say("New done.", WHITE);
break;
case IN_OPEN:
fileopen(FALSE);
break;
case IN_REVERT:
fileopen(TRUE);
break;
case IN_SAVE:
filesaveas(FALSE);
break;
case IN_SAVEAS:
filesaveas(TRUE);
break;
case IN_PROJECTDELETE:
filedelete();
break;
case IN_QUIT:
if (verify())
cleanexit(EXIT_SUCCESS);
break;
default:
break;
}
break;
case MN_SETTINGS:
switch(ITEMNUM(code))
{
case IN_ANIMATIONS:
if (ItemPtr->Flags & CHECKED)
{ anims = TRUE;
} else
{ anims = FALSE;
}
break;
case IN_CREATEICONS:
if (ItemPtr->Flags & CHECKED)
{ icons = TRUE;
} else
{ icons = FALSE;
}
break;
case IN_ENGRAVEDSQUARES:
if (ItemPtr->Flags & CHECKED)
{ engraved = TRUE;
} else
{ engraved = FALSE;
}
break;
case IN_SHOWTITLEBAR:
if (ItemPtr->Flags & CHECKED)
{ titlebar = TRUE;
} else
{ titlebar = FALSE;
}
ShowTitle(ScreenPtr, titlebar);
break;
default:
break;
}
break;
case MN_HELP:
switch(ITEMNUM(code))
{
case IN_ABOUT:
helpabout();
break;
case IN_CREATURES:
help(ORB);
break;
case IN_OBJECTS:
help(AFFIXER);
break;
default:
break;
}
break;
default:
break;
}
code = ItemPtr->NextSelect;
}
break;
case IDCMP_MOUSEBUTTONS:
if (code == SELECTDOWN)
{ if (ignore)
{ ignore = FALSE;
} else
{ a = PLAYGAME;
} }
break;
case IDCMP_REFRESHWINDOW:
GT_BeginRefresh(MainWindowPtr);
GT_EndRefresh(MainWindowPtr, TRUE);
break;
case IDCMP_GADGETUP:
if (WhichGadgetPtr == ShuffleGadgetPtr)
{ randomflag = !randomflag;
} else
{ for (player = 0; player <= 3; player++)
{ if (WhichGadgetPtr == CycleGadgetPtr[player])
{ worm[player].control = code;
break;
} } }
break;
case IDCMP_ACTIVEWINDOW:
ignore = TRUE;
break;
case IDCMP_CLOSEWINDOW:
cleanexit(EXIT_SUCCESS);
break;
case IDCMP_INTUITICKS:
if (anims)
{ drawboing();
// cyclecolours();
for (i = 0; i <= HISCORES; i++)
{ if (hiscore[i].player != -1)
{ Image.ImageData = ImageData[missileframes[hiscore[i].player][hiframe]];
DrawImage(MainWindowPtr->RPort, &Image, CENTREXPIXEL + 220, YSTART + 133 + (i * HISCOREDISTANCE));
if (++hiframe > MISSILEFRAMES)
{ hiframe = 0;
} } } }
if (firebutton())
{ a = PLAYGAME;
}
break;
default:
; /* IDCMP_MENUVERIFY */
break;
} }
if (a == PLAYGAME)
{ if (worm[0].control == NONE && worm[1].control == NONE && worm[2].control == NONE && worm[3].control == NONE)
{ say("No worms active!", WHITE);
anykey(TRUE);
a = GAMEOVER;
} elif
( !LowLevelBase &&
(worm[0].control == GAMEPAD
|| worm[1].control == GAMEPAD
|| worm[2].control == GAMEPAD
|| worm[3].control == GAMEPAD
) )
{ say("Need OS3.1+ for gamepad!", WHITE);
anykey(TRUE);
a = GAMEOVER;
} } }
while (a == GAMEOVER);
for (player = 0; player <= 3; player++)
{ GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
}
GT_SetGadgetAttrs(ShuffleGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
if (a == FIELDEDIT)
{ fieldedit();
} else
{ assert(a == PLAYGAME);
turbo = FALSE;
newgame();
clearkybd();
Forbid();
MainWindowPtr->Flags |= WFLG_RMBTRAP;
Permit();
} }
EXPORT void toggle(SBYTE key)
{ PERSIST ABOOL songstarted = FALSE;
switch(key)
{
case F:
if (mode == FX) /* F in FX mode: no sound */
{ freefx();
mode = FALSE;
draw(MUSICICON, ICONY, BLACKENED);
} else if (fxable != FAILED) /* F otherwise: change to FX mode */
{ if (mode == MUSIC) /* stop any music that is playing */
{ StopPlayer();
FreePlayer();
}
if (fxable == DEFER) /* load samples if needed */
loadthefx();
if (fxable == SUCCEEDED) /* if we have samples in memory */
{ if (beginfx())
{ mode = FX;
effect(FXGET_RAIN);
draw(MUSICICON, ICONY, FX);
} } }
break;
case M:
if (mode == MUSIC) /* M in MUSIC mode: no sound */
{ StopPlayer();
FreePlayer();
mode = FALSE;
draw(MUSICICON, ICONY, BLACKENED);
} else if (musicable != FAILED) /* M otherwise: change to music mode */
{ if (mode == FX) /* stop any samples that are playing */
freefx();
/* Of course, these statements are ordered in this
way for a reason, so don't change it. :-) */
if (musicable == DEFER)
loadthemusic();
if (musicable == SUCCEEDED)
{ if (GetPlayer(0))
{ say("No channels for music!", RED);
anykey(TRUE);
mode = FALSE;
draw(MUSICICON, ICONY, BLACKENED);
} else
{ if (songstarted)
ContModule(SongPtr[song]);
else
{ PlayModule(SongPtr[song]);
songstarted = TRUE;
}
mode = MUSIC;
draw(MUSICICON, ICONY, MUSIC);
} } }
break;
default:
flash(2);
assert(0);
break;
} }
EXPORT ABOOL verify(void)
{ if (modified && (EasyRequest(MainWindowPtr, &EasyStruct, NULL) == 0))
return FALSE;
else return TRUE;
}
EXPORT void waitasec(void)
{ Delay(50);
}
EXPORT void systemsetup(void)
{ worm[0].control = NONE;
worm[1].control = KEYBOARD;
worm[2].control = NONE;
worm[3].control = AMIGA;
}
EXPORT ABOOL ZOpen(STRPTR fieldname, ABOOL write)
{ if (!write)
if (FilePtr = Open(fieldname, MODE_OLDFILE))
return TRUE;
else return FALSE;
else
if (FilePtr = Open(fieldname, MODE_NEWFILE))
return TRUE;
else return FALSE;
}
EXPORT ABOOL ZRead(STRPTR IOBuffer, ULONG length)
{ if (Read(FilePtr, IOBuffer, length) == length)
return TRUE;
else return FALSE;
}
EXPORT ABOOL ZWrite(STRPTR IOBuffer, ULONG length)
{ if (Write(FilePtr, IOBuffer, length) == length)
return TRUE;
else return FALSE;
}
EXPORT ABOOL ZClose(void)
{ if (Close(FilePtr))
{ FilePtr = NULL;
return TRUE;
} else
{ /* "If Close() returns DOSFALSE, the user has already cancelled an
error requester and the function has already freed the FileHandle
(and even marked it so any attempt to close it again will bring up
the "Software Failure" requester). Therefore FilePtr should be set
to zero in any case." - Jilles Tjoelker. */
FilePtr = NULL;
return FALSE;
} }
EXPORT void timing(void)
{ ;
}
EXPORT void clearscreen(void)
{ SBYTE i, j;
if (DisplayDepth >= DEPTH5)
{ drawbackground();
} else
{ SetAPen(MainWindowPtr->RPort, BLACK);
RectFill(MainWindowPtr->RPort, 0, 0, ENTIREXPIXEL, ENTIREYPIXEL);
}
if (mode == MUSIC)
draw(MUSICICON, ICONY, MUSIC);
elif (mode == FX)
draw(MUSICICON, ICONY, FX);
else draw(MUSICICON, ICONY, BLACKENED);
draw(CLOCKICON, ICONY, BLACKENED);
clockdrawn = FALSE;
if (a != FIELDEDIT && !first)
{ for (i = 0; i <= 3; i++)
{ if (worm[i].control != NONE)
{ draw(-6, (i * 10) , BONUS);
draw(-6, (i * 10) + 1, MINIHEALER);
draw(-6, (i * 10) + 2, BRAKES);
draw(-6, (i * 10) + 3, AMMO);
draw(-6, (i * 10) + 4, POWER);
for (j = 0; j <= LASTOBJECT; j++)
{ icon(i, j);
} } } }
first = FALSE;
}
EXPORT void datestamp(void)
{ ULONG seconds, micros;
struct ClockData Date;
TEXT temp[5];
CurrentTime(&seconds, µs);
Amiga2Date(seconds, &Date);
stci_d(times, Date.hour); /* hh */
align(times, 2, ' ');
times[2] = ':'; /* hh: */
times[3] = 0;
stci_d(temp, Date.min);
align(temp, 2, '0');
temp[2] = 0;
strcat(times, temp); /* hh:mm */
stci_d(date, Date.mday); /* dd */
align(date, 2, ' ');
date[2] = '/';
date[3] = 0; /* dd/ */
stci_d(temp, Date.month);
align(temp, 2, ' ');
temp[2] = 0;
strcat(date, temp); /* dd/mm */
strcat(date, "/"); /* dd/mm/ */
stci_d(temp, Date.year);
temp[0] = temp[2];
temp[1] = temp[3];
temp[2] = 0;
strcat(date, temp); /* dd/mm/yy */
}
EXPORT void turborender(void)
{ UBYTE random = rand() % 3;
SBYTE x, y;
if (a != PLAYGAME || (!level) || !(randomflag))
sourcelevel = level;
if (a == FIELDEDIT)
{ for (x = 0; x <= MINFIELDX; x++)
{ for (y = 0; y <= MINFIELDY; y++)
{ fedraw(x, y, board[level][x][y]);
} } }
else
{ changefield();
switch(random)
{
case 0:
for (x = 0; x <= fieldx; x += 2)
{ for (y = 0; y <= fieldy; y += 2)
{ draw(x, y, field[x][y]);
}
if (x < fieldx)
{ for (y = 1; y <= fieldy; y += 2)
{ draw(x + 1, y, field[x + 1][y]);
} } }
for (x = 0; x <= fieldx; x += 2)
{ for (y = 1; y <= fieldy; y += 2)
{ draw(x, y, field[x][y]);
}
if (x < fieldx)
{ for (y = 0; y <= fieldy; y += 2)
{ draw(x + 1, y, field[x + 1][y]);
} } }
break;
case 1:
for (y = 0; y <= fieldy; y += 2)
{ for (x = 0; x <= fieldx; x++)
{ draw(x, y, field[x][y]);
} }
for (y = 1; y <= fieldy; y += 2)
{ for (x = 0; x <= fieldx; x++)
{ draw(x, y, field[x][y]);
} }
break;
case 2:
for (y = 0; y <= fieldy; y += 2)
{ for (x = 0; x <= fieldx; x++)
{ draw(x, y, field[x][y]);
}
if (y < fieldy)
{ for (x = fieldx; x >= 0; x--)
{ draw(x, y + 1, field[x][y + 1]);
} } }
break;
default:
assert(0);
break;
} }
if (a == FIELDEDIT)
{ fedraw(startx[sourcelevel], starty[sourcelevel], START);
dot();
} else
{ for (y = 0; y <= fieldy; y++)
{ draw(ARROWX, y, BLACKARROW);
} }
SetAPen(MainWindowPtr->RPort, MEDIUMGREY);
if (a == FIELDEDIT)
{ Move(MainWindowPtr->RPort, STARTXPIXEL + ( LEFTGAP * SQUAREX) , ENDYPIXEL - (BOTTOMGAP * SQUAREY) + 1);
Draw(MainWindowPtr->RPort, ENDXPIXEL - (RIGHTGAP * SQUAREX) , ENDYPIXEL - (BOTTOMGAP * SQUAREY) + 1);
Move(MainWindowPtr->RPort, ENDXPIXEL - (RIGHTGAP * SQUAREX) + 1, STARTYPIXEL + ( TOPGAP * SQUAREY) );
Draw(MainWindowPtr->RPort, ENDXPIXEL - (RIGHTGAP * SQUAREX) + 1, ENDYPIXEL - (BOTTOMGAP * SQUAREY) + 1);
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, STARTXPIXEL + ( LEFTGAP * SQUAREX) + 1, ENDYPIXEL - (BOTTOMGAP * SQUAREY) + 2);
Draw(MainWindowPtr->RPort, ENDXPIXEL - (RIGHTGAP * SQUAREX) + 1, ENDYPIXEL - (BOTTOMGAP * SQUAREY) + 2);
Move(MainWindowPtr->RPort, ENDXPIXEL - (RIGHTGAP * SQUAREX) + 2, STARTYPIXEL + ( TOPGAP * SQUAREY) + 1);
Draw(MainWindowPtr->RPort, ENDXPIXEL - (RIGHTGAP * SQUAREX) + 2, ENDYPIXEL - (BOTTOMGAP * SQUAREY) + 2);
} else
{ Move(MainWindowPtr->RPort, STARTXPIXEL , ENDYPIXEL + 1);
Draw(MainWindowPtr->RPort, ENDXPIXEL , ENDYPIXEL + 1);
Move(MainWindowPtr->RPort, ENDXPIXEL + 1, STARTYPIXEL );
Draw(MainWindowPtr->RPort, ENDXPIXEL + 1, ENDYPIXEL + 1);
SetAPen(MainWindowPtr->RPort, BLACK);
Move(MainWindowPtr->RPort, STARTXPIXEL + 1, ENDYPIXEL + 2);
Draw(MainWindowPtr->RPort, ENDXPIXEL + 1, ENDYPIXEL + 2);
Move(MainWindowPtr->RPort, ENDXPIXEL + 2, STARTYPIXEL + 1);
Draw(MainWindowPtr->RPort, ENDXPIXEL + 2, ENDYPIXEL + 2);
} }
EXPORT void ReadAdapterJoystick(UBYTE unit)
{ AUTO UBYTE firebit, addroffset, snapshot;
AUTO SBYTE xx = 0, yy = 0;
AUTO ABOOL fire = FALSE;
PERSIST UBYTE oldsnapshot[2] = {0, 0};
PERSIST ABOOL oldfire[2] = {0, 0};
PERSIST UBYTE *fireaddrPtr,
*moveaddrPtr;
fireaddrPtr = (UBYTE *) 0xBFD000;
moveaddrPtr = (UBYTE *) 0xBFE101;
/* Those pointers could easily be auto or constant or whatever; they
never change.
bit 7 of $bfe101 is right of joystick '4'
bit 6 of $bfe101 is left of joystick '4'
bit 5 of $bfe101 is down of joystick '4'
bit 4 of $bfe101 is up of joystick '4'
bit 3 of $bfe101 is right of joystick '3'
bit 2 of $bfe101 is left of joystick '3'
bit 1 of $bfe101 is down of joystick '3'
bit 0 of $bfe101 is up of joystick '3'
bit 2 of $bfd000 is fire of joystick '3'
bit 0 of $bfd000 is fire of joystick '4'
unit: number of the unit (2 = '3', 3 = '4') */
if (unit == 2)
{ firebit = 2;
addroffset = 0;
} else
{ assert(unit == 3);
firebit = 0;
addroffset = 4;
}
if (worm[unit].control == JOYSTICK && worm[unit].lives)
{ if ((*fireaddrPtr) & (1 << firebit))
fire = TRUE;
snapshot = *moveaddrPtr; // we cache this address in the snapshot
// variable, so that joystick reading is an
// atomic operation
if (snapshot & (1 << (addroffset + 3)))
xx = 1;
elif (snapshot & (1 << (addroffset + 2)))
xx = -1;
if (snapshot & (1 << (addroffset + 1)))
yy = 1;
elif (snapshot & (1 << addroffset ))
yy = -1;
if (oldsnapshot[unit - 2] != snapshot || oldfire[unit - 2] != fire)
{ if (fire)
wormqueue(unit, 0, 0);
else
wormqueue(unit, xx, yy);
}
oldsnapshot[unit - 2] = snapshot;
oldfire[unit - 2] = fire;
} }
EXPORT void ReadStandardJoystick(ULONG port)
{ AUTO UBYTE PortState[2];
AUTO ABOOL fire = FALSE;
AUTO SBYTE xx = 0,
yy = 0,
player;
PERSIST UBYTE OldPortState[2] = {0, 0};
if (port == 1)
{ player = 2; // blue worm
} else
{ assert(port == 0);
player = 3; // yellow worm
}
if (worm[player].control == JOYSTICK && worm[player].lives)
{ PortState[port] = ReadJoystick(port);
if (PortState[port] != OldPortState[port])
{ if (PortState[port] & JOYUP)
yy = -1;
elif (PortState[port] & JOYDOWN)
yy = 1;
if (PortState[port] & JOYLEFT)
xx = -1;
elif (PortState[port] & JOYRIGHT)
xx = 1;
if (PortState[port] & JOYFIRE1)
{ fire = TRUE;
}
// this doesn't work perfectly?
if (PortState[port] != 0 && (worm[player].brakes || xx == 0 || yy == 0))
// if joystick is off-centre or firebutton is down
{ if (fire) // if firebutton is down
{ wormqueue(player, 0, 0); // then shoot/jump
} else // if firebutton is up
{ wormqueue(player, xx, yy); // then move
} } }
OldPortState[port] = PortState[port];
} }
EXPORT void flash(ULONG where)
{ TEXT saystring[SAYLIMIT + 1];
stci_d(saystring, where);
say(saystring, PURPLE);
while(1);
}
EXPORT void ReadGamepads(void)
{ AUTO ULONG PortState;
AUTO ABOOL fire = FALSE;
AUTO SBYTE i, xx = 0, yy = 0;
PERSIST ULONG OldPortState = 0;
for (i = 0; i <= 3; i++)
{ if (worm[i].control == GAMEPAD && worm[i].lives)
{ PortState = ReadJoyPort(worm[i].port);
if (PortState != OldPortState)
{ if (PortState & JP_BUTTON_MASK)
{ fire = TRUE;
}
if (PortState & JPF_JOY_UP)
{ yy = -1;
} elif (PortState & JPF_JOY_DOWN)
{ yy = 1;
}
if (PortState & JPF_JOY_LEFT)
{ xx = -1;
} elif (PortState & JPF_JOY_RIGHT)
{ xx = 1;
}
if (fire) // if firebutton is down
{ wormqueue(i, 0, 0); // then shoot/jump
} elif (xx || yy)
{ wormqueue(i, xx, yy);
} }
OldPortState = PortState;
} } }
EXPORT void whiteline(void)
{ SetAPen(MainWindowPtr->RPort, WHITE);
}
EXPORT void colourline(SBYTE player)
{ SetAPen(MainWindowPtr->RPort, worm[player].colour);
}
#ifdef __STORM__
EXPORT int stci_d(char* out, int lvalue)
{ return(stcl_d(out, lvalue));
}
EXPORT int stcl_d(char* out, long lvalue)
{ ULONG calc,
i,
where;
FLAG started = FALSE;
if (lvalue < 0)
{ out[0] = '-';
where = 1;
lvalue = abs(lvalue);
} else
{ where = 0;
}
for (i = ONE_BILLION; i >= 1; i /= 10)
{ calc = lvalue / i;
assert(calc < 10);
if (calc || started || i == 1)
{ *(out + where) = (char) ('0' + calc);
where++;
started = TRUE;
}
lvalue %= i;
}
*(out + where) = 0;
return(where);
}
#endif
EXPORT void playsong(UBYTE whichsong)
{ if (song != whichsong)
{ song = whichsong;
if (mode == MUSIC && musicable)
{ StopPlayer();
PlayModule(SongPtr[song]);
} } }